【ProjectEuler】ProjectEuler_051(找出最小的能够通过改变同一部分得到八个质数的质数)
2013-03-24 21:46
281 查看
#pragma once #include <windows.h> #include <vector> #include <set> using namespace std; class MoonMath { public: MoonMath(void); ~MoonMath(void); //************************************ // Method: IsInt // Access: public // Describe: 判断double值在epsilon的范围内是否很接近整数 // 如1.00005在epsilon为0.00005以上就很接近整数 // Parameter: double doubleValue 要判断的double值 // Parameter: double epsilon 判断的精度,0 < epsilon < 0.5 // Parameter: INT32 & intValue 如果接近,返回最接近的整数值 // Returns: bool 接近返回true,否则返回false //************************************ static bool IsInt(double doubleValue, double epsilon, INT32 &intValue); //************************************ // Method: Sign // Access: public // Describe: 获取value的符号 // Parameter: T value 要获取符号的值 // Returns: INT32 正数、0和负数分别返回1、0和-1 //************************************ template <typename T> static INT32 Sign(T value); const static UINT32 MIN_PRIMER = 2; // 最小的素数 //************************************ // Method: IsPrimer // Access: public // Describe: 判断一个数是否是素数 // Parameter: UINT32 num 要判断的数 // Returns: bool 是素数返回true,否则返回false //************************************ static bool IsPrimer(UINT32 num); //************************************ // Method: IsIntegerSquare // Access: public static // Describe: 判断给定的数开平方后是否为整数 // Parameter: UINT32 num // Returns: bool //************************************ static bool IsIntegerSquare(UINT32 num); //************************************ // Method: GetDiffPrimerFactorNum // Access: public static // Describe: 获取num所有的不同质因数 // Parameter: UINT32 num // Returns: set<UINT32> //************************************ static set<UINT32> MoonMath::GetDiffPrimerFactorNum(UINT32 num); };
#include "MoonMath.h" #include <cmath> MoonMath::MoonMath(void) { } MoonMath::~MoonMath(void) { } template <typename T> INT32 MoonMath::Sign(T value) { if(value > 0) { return 1; } else if(value == 0) { return 0; } else { return -1; } } bool MoonMath::IsInt(double doubleValue, double epsilon, INT32 &intValue) { if(epsilon > 0.5 || epsilon < 0) { return false; } if(INT32(doubleValue + epsilon) == INT32(doubleValue - epsilon)) { return false; } INT32 value = INT32(doubleValue); intValue = (fabs(doubleValue - value) > 0.5) ? (value + MoonMath::Sign(doubleValue)) : (value) ; return true; } bool MoonMath::IsPrimer(UINT32 num) { if(num < MIN_PRIMER) { return false; } if(num == MIN_PRIMER) { return true; } // 判断是否能被2整除 if((num & 1) == 0) { return false; } UINT32 sqrtOfNum = (UINT32)sqrt((double)num); // num的2次方 // 从MIN_PRIMER到sqrt(num),如果任何数都不能被num整除,num是素数,否则不是 for(UINT32 i = MIN_PRIMER + 1; i <= sqrtOfNum; i += 2) { if(num % i == 0) { return false; } } return true; } bool MoonMath::IsIntegerSquare(UINT32 num) { UINT32 qurtNum = (UINT32)sqrt((double)num); return (qurtNum * qurtNum) == num; } set<UINT32> MoonMath::GetDiffPrimerFactorNum(UINT32 num) { UINT32 halfNum = num / 2; set<UINT32> factors; for(UINT32 i = 2; i <= halfNum; ++i) { if(!MoonMath::IsPrimer(i)) { continue; } if(num % i == 0) { factors.insert(i); while(num % i == 0) { num /= i; } } } return factors; }
// Prime digit replacements // Problem 51 // By replacing the 1st digit of *3, it turns out that six of the nine possible values: 13, 23, 43, 53, 73, and 83, are all prime. // // By replacing the 3rd and 4th digits of 56**3 with the same digit, this 5-digit number is the first example having seven primes among the ten generated numbers, yielding the family: 56003, 56113, 56333, 56443, 56663, 56773, and 56993. Consequently 56003, being the first member of this family, is the smallest prime with this property. // // Find the smallest prime which, by replacing part of the number (not necessarily adjacent digits) with the same digit, is part of an eight prime value family. // // 题目51:找出最小的能够通过改变同一部分得到八个质数的质数。 // 通过置换*3的第一位得到的9个数中,有六个是质数:13,23,43,53,73和83。 // // 通过用同样的数字置换56**3的第三位和第四位,这个五位数是第一个能够得到七个质数的数字,得到的质数是:56003, 56113, 56333, 56443, 56663, 56773, 和 56993。因此其中最小的56003就是具有这个性质的最小的质数。 // // 找出最小的质数,通过用同样的数字置换其中的一部分(不一定是相邻的部分),能够得到八个质数。 #include <iostream> #include <windows.h> #include <ctime> #include <assert.h> #include <vector> #include <MoonMath.h> using namespace std; // 打印时间等相关信息 class DetailPrinter { public: void Start(); void End(); DetailPrinter(); private: LARGE_INTEGER timeStart; LARGE_INTEGER timeEnd; LARGE_INTEGER freq; }; DetailPrinter::DetailPrinter() { QueryPerformanceFrequency(&freq); } //************************************ // Method: Start // Access: public // Describe: 执行每个方法前调用 // Returns: void //************************************ void DetailPrinter::Start() { QueryPerformanceCounter(&timeStart); } //************************************ // Method: End // Access: public // Describe: 执行每个方法后调用 // Returns: void //************************************ void DetailPrinter::End() { QueryPerformanceCounter(&timeEnd); cout << "Total Milliseconds is " << (double)(timeEnd.QuadPart - timeStart.QuadPart) * 1000 / freq.QuadPart << endl; const char BEEP_CHAR = '\007'; cout << endl << "By GodMoon" << endl << __TIMESTAMP__ << BEEP_CHAR << endl; system("pause"); } /*************************解题开始*********************************/ const UINT32 RADIO = 10; // 进制 // 记录最小素数,可以增加的数以及可增加的次数 // 比如56003,可以增加的数为100,110,10,可增加的次数分别为9,9,9 struct FitInfo { UINT32 Num; vector<UINT32> IncNums; vector<UINT32> MaxIncTimes; void Clear(); void AddIncNum(UINT32 incNum, UINT32 maxIncTimes); }; //************************************ // Method: Clear // Access: public // Describe: 清空信息 // Returns: void //************************************ void FitInfo::Clear() { Num = 0; IncNums.clear(); MaxIncTimes.clear(); } //************************************ // Method: AddIncNum // Access: public // Describe: // Parameter: UINT32 incNum // Parameter: UINT32 maxIncTimes // Returns: void //************************************ void FitInfo::AddIncNum(UINT32 incNum, UINT32 maxIncTimes) { IncNums.push_back(incNum); MaxIncTimes.push_back(maxIncTimes); } //************************************ // Method: GetFitInfo // Access: public // Describe: 获取这个数的信息,替换连续的相同数字 // Parameter: UINT32 num // Parameter: FitInfo & fitInfo // Returns: void //************************************ void GetAdjacentFitInfo(UINT32 num, FitInfo &fitInfo, UINT32 familyPrimerCount) { UINT32 numBak = num; // 备份num,用于循环 UINT32 currDigit; // 当前处理的数字 UINT32 lastDigit = num % RADIO; // 前一个处理的数字,初始化为第一个数字 UINT32 currWeight = 1; // 当前位的权重,为1,10,100…… UINT32 currIncNum = 0; // 当前num可增加的数 UINT32 addNum; // 用于递增计算连续可用的递增数 UINT32 incNum; // 用于保存连续可用的递增数 fitInfo.Clear(); fitInfo.Num = num; while(numBak != 0) { currDigit = numBak % RADIO; if(currDigit <= RADIO - familyPrimerCount) { // 如果上一个数字和当前数字一致,将其组合加入fitInfo if(lastDigit == currDigit) { currIncNum += currWeight; addNum = currWeight; for(incNum = currWeight; incNum < currIncNum; incNum += addNum) { addNum /= RADIO; fitInfo.AddIncNum(incNum, RADIO - currDigit - 1); } } else { // 不一致的话,只添加currWeight currIncNum = currWeight; } fitInfo.AddIncNum(currIncNum, RADIO - currDigit - 1); } else { currIncNum = 0; } currWeight *= 10; lastDigit = currDigit; numBak /= RADIO; } } //************************************ // Method: GetNumMap // Access: public // Describe: 获取 // Parameter: UINT32 num // Parameter: UINT32 digitIncNum[] 二进制的数字map,表示索引的数字所在十进制数中的位置 // Parameter: UINT32 radio // Returns: void //************************************ void GetNumMap(UINT32 num, UINT32 digitIncMap[], UINT32 radio) { UINT32 currDigit; UINT32 currWeight = 1; while(num != 0) { currDigit = num % radio; digitIncMap[currDigit] |= currWeight; currWeight <<= 1; num /= radio; } } //************************************ // Method: GetIncWeight // Access: public // Describe: 根据二进制Map获取可加权重 // Parameter: UINT32 digitIncMap 如:1010B // Parameter: vector<UINT32> & incWeight 如:1000,10 // Returns: void //************************************ void GetIncWeight(UINT32 digitIncMap, vector<UINT32> &incWeight) { UINT32 currWeight = 1; incWeight.clear(); while(digitIncMap != 0) { if((digitIncMap & 1)) { incWeight.push_back(currWeight); } currWeight *= RADIO; digitIncMap >>= 1; } } //************************************ // Method: GetValue // Access: public // Describe: 从map和权重中获取值 // Parameter: UINT32 map 数据位,如:101 // Parameter: vector<UINT32> & incWeight 权重,如:1000,100,1 // Returns: UINT32 值:如:1001 //************************************ UINT32 GetValue(UINT32 map, const vector<UINT32> &incWeight) { UINT32 value; UINT32 index; for(value = 0, index = 0; map; ++index) { if(map & 1) { value += incWeight[index]; } map >>= 1; } return value; } //************************************ // Method: ParseDigitMap // Access: public // Describe: 从digitIncMap中计算出相应数字的fitInfo // Parameter: UINT32 digitIncMap 表示数字digit的所在位比如10101101 // Parameter: UINT32 digit 范围[0,RADIO),表示某个数字 // Parameter: FitInfo & fitInfo // Returns: void //************************************ void ParseDigitMap(UINT32 digitIncMap, UINT32 digit, FitInfo &fitInfo) { vector<UINT32> incWeight; GetIncWeight(digitIncMap, incWeight); UINT32 maxMapValue = 1 << incWeight.size(); for(UINT32 mapValue = 1; mapValue < maxMapValue; ++mapValue) { fitInfo.AddIncNum(GetValue(mapValue, incWeight), RADIO - digit - 1); } } //************************************ // Method: GetFitInfo // Access: public // Describe: 获取这个数的信息,替换不一定连续的相同数字 // Parameter: UINT32 num // Parameter: FitInfo & fitInfo // Returns: void //************************************ void GetNotAdjacentFitInfo(UINT32 num, FitInfo &fitInfo, UINT32 familyPrimerCount) { UINT32 digitIncMap[RADIO] = {0}; fitInfo.Clear(); fitInfo.Num = num; GetNumMap(num, digitIncMap, RADIO); for(UINT32 digit = 0; digit < RADIO; ++digit) { ParseDigitMap(digitIncMap[digit], digit, fitInfo); } } //************************************ // Method: CalcMaxPrimerCount // Access: public // Describe: 获取此族素数的个数 // Parameter: const FitInfo & fitInfo // Returns: UINT32 //************************************ UINT32 CalcMaxPrimerCount(const FitInfo &fitInfo, UINT32 &maxFitIncNum, UINT32 &maxFitTimes) { UINT32 maxPrimerCount = 0; UINT32 currPrimerCount = 1; UINT32 fitCount = fitInfo.IncNums.size(); UINT32 currNum; UINT32 fitIndex; UINT32 fitIncTimes; UINT32 fitIncCount; UINT32 fitIncNum; for(fitIndex = 0; fitIndex < fitCount; ++fitIndex) { currPrimerCount = 1; // 初始化为1,因为fitInfo.Num已经是素数了 currNum = fitInfo.Num; fitIncNum = fitInfo.IncNums[fitIndex]; fitIncTimes = fitInfo.MaxIncTimes[fitIndex]; for(fitIncCount = 0; fitIncCount < fitIncTimes; ++fitIncCount) { currNum += fitIncNum; if(MoonMath::IsPrimer(currNum)) { ++currPrimerCount; if(currPrimerCount > maxPrimerCount) { maxFitIncNum = fitIncNum; maxFitTimes = fitIncTimes; maxPrimerCount = currPrimerCount; } } } } return maxPrimerCount; } void TestFun1() { FitInfo fitInfo; GetNotAdjacentFitInfo(100, fitInfo, 8); cout << "Test OK!" << endl; } void F1() { cout << "void F1()" << endl; // TestFun1(); DetailPrinter detailPrinter; detailPrinter.Start(); /*********************************算法开始*******************************/ const UINT32 FAMILY_PRIMER_COUNT = 6; // 素数族中素数个数 FitInfo fitInfo; UINT32 maxFitIncNum; UINT32 maxFitTimes; for(UINT32 num = 3;; num += 2) { if(MoonMath::IsPrimer(num)) { GetNotAdjacentFitInfo(num, fitInfo, FAMILY_PRIMER_COUNT); if(CalcMaxPrimerCount(fitInfo, maxFitIncNum, maxFitTimes) >= FAMILY_PRIMER_COUNT) { break; } } } cout << "拥有至少" << FAMILY_PRIMER_COUNT << "个素数的素数族中最小的素数为" << fitInfo.Num << endl << "素数族其他成员为:"; UINT32 primer = fitInfo.Num; for(UINT32 i = 0; i < maxFitTimes; ++i) { primer += maxFitIncNum; if(MoonMath::IsPrimer(primer)) { cout << primer << " "; } } cout << endl; /*********************************算法结束*******************************/ detailPrinter.End(); } //主函数 int main() { F1(); return 0; } /* void F1() 拥有至少6个素数的素数族中最小的素数为13 素数族其他成员为:23 43 53 73 83 Total Milliseconds is 4.50833 By GodMoon Sun Mar 24 21:44:13 2013 void F1() 拥有至少7个素数的素数族中最小的素数为56003 素数族其他成员为:56113 56333 56443 56663 56773 56993 Total Milliseconds is 481.138 By GodMoon Sun Mar 24 21:43:49 2013 void F1() 拥有至少8个素数的素数族中最小的素数为121313 素数族其他成员为:222323 323333 424343 525353 626363 828383 929393 Total Milliseconds is 1023.6 By GodMoon Sun Mar 24 21:41:17 2013 */
相关文章推荐
- 剑指offer-定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。
- 2014-05-13MFC对话框:改变MFC中按钮的文字,更改窗体的大小,通过类名能够查找到该类对应的对话框,MFC中获取文本框中的内容,updatedata函数,两种对话框比较,oncreate起点
- 小易邀请你玩一个数字游戏,小易给你一系列的整数。你们俩使用这些整数玩游戏。每次小易会任意说一个数字出来,然后你需要从这一系列数字中选取一部分出来让它们的和等于小易所说的数字。 例如: 如果{2,1,2,7}是你有的一系列数,小易说的数字是11.你可以得到方案2+2+7 = 11.如果顽皮的小易想坑你,他说的数字是6,那么你没有办法拼凑出和为6 现在小易给你n个数,让你找出无法从n个数中选取部分求和
- 对于"容量分别为A与B的两个水桶,是否能够通过互相倒水可以得到1~MAX(A,B)所有容量的水"问题的分析
- 定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素。o(1)空间的代码实现
- 定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素。要求函数min、push以及pop的时间复杂度都是O(1)
- 定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。
- 2定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素
- 剑指offer——定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。
- C#中的PropertyGrid绑定对象,通过改变某一值而动态设置部分属性的特性
- 1通过URL对象的openStream()方法能够得到指定资源的输入流。
- C++11 FAQ中文版:std::function 和 std::bind(在cocos2dx中:bind能够把类内函数转成类外函数(通过传入这个类的指针 this 得到被捆绑的成员函))
- malloc和free(3)——malloc()申请内存得到指针,通过memcpy()拷贝数据到指针所指内存,指针没有改变,调用free()释放内存不会报错
- js通过八个点 拖动改变div大小的实现方法
- 面试题:定义栈的数据结构,要求添加一个min函数,能够得到栈的最小元素,要求函数min,push及pop的时间复杂度都是O(1)
- 定义栈的数据结构,要求添加一个 min 函数,能够得到栈的最小元素。要求函数 min、push 以及 pop 的时间复杂度都是 O(1)。
- js通过八个点 拖动改变div大小
- 定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数
- 定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。时间复杂度都是O(1)
- Android中通过反射和getResource()得到id的方式去改变View的显示效果