GMP库mpz_t变量赋值异常 欧拉29题大整数去重实现出错
问题原因
你的判断是准确的,vector中存储的所有元素都是同一个rop变量的内存地址。每次循环中调用mpz_ui_pow_ui修改rop的值时,vector里所有指针指向的内容都会同步更新,所以对比时会永远判定为相等,自然无法插入新值。如果直接在push_back后调用mpz_clear(rop),vector里存储的所有指针都会变成野指针,访问时会直接触发内存错误。
修复方案
- 不要直接存储复用的
rop变量的指针,每次确认要存储新的幂运算结果时,单独初始化一个新的mpz_t实例,将当前rop的值拷贝到新实例中,再将新实例的指针存入vector。 - 程序运行结束后,遍历vector释放所有存储的
mpz_t实例,避免内存泄漏。
修改后的完整代码
#include <iostream> #include <vector> #include <chrono> #include "gmp.h" using namespace std; int main() { auto start = std::chrono::high_resolution_clock::now(); int solution = 0; bool found = false; int r = 10; mpz_t rop; mpz_init(rop); mpz_t temp; mpz_init(temp); vector<mpz_t*> numbers; // 测试范围可按需改回2~100 for(int a = 2; a <= 5; a++) { for(int b = 2; b <= 5; b++) { mpz_ui_pow_ui(rop, a, b); found = false; for(int i = 0; i < numbers.size(); i++) { mpz_set(temp,*(numbers.at(i))); r = mpz_cmp(rop,temp); if(r == 0) { found = true; break; } } if(found == false) { // 新建mpz_t实例,拷贝当前rop的值再存入vector mpz_t* new_num = new mpz_t; mpz_init(*new_num); mpz_set(*new_num, rop); numbers.push_back(new_num); solution++; } } } auto done = std::chrono::high_resolution_clock::now(); cout << "Solution: " << solution << endl << endl; cout << "Program completed in " << std::chrono::duration_cast<std::chrono::milliseconds>(done - start).count() << " milliseconds." << endl; // 释放所有存储的mpz_t资源 for(auto num : numbers) { mpz_clear(*num); delete num; } // 释放临时变量资源 mpz_clear(rop); mpz_clear(temp); return 0; }
额外优化建议
如果要计算a、b范围到100的正式题解,用vector遍历查重的效率较低,你可以改用std::set结构存储结果,利用set自带的去重特性简化代码,需要注意自定义mpz_t的比较逻辑,或者直接将mpz_t转为字符串存入set即可。
内容的提问来源于stack exchange,提问作者MFerguson
相关产品推荐
相关产品推荐

