PE51
題意: 問最小的連續八個的素數家庭組 的最小素數, 其中素數家庭組 有部分重複數字 其他為遞增的數字
類似如下格式
56* *3
56003
56113
56333
56443
56663
56773
56993
然後真不會做, 看了這篇題解以後發現重複的數字必是 三個 才有可能出現八個素數(mathblog.dk/project-euler-51-eight-prime-family/)
Result(mod 3) 模3的答案 | Number of repeated digits 重複的數字數 | ||||
1 | 2 | 3 | 4 | 5 | |
0 | 4 | 4 | 10 | 4 | 4 |
1 | 3 | 3 | 0 | 3 | 3 |
2 | 3 | 3 | 0 | 3 | 3 |
一個數是否能整除3 可以根據各個位上的數字之和 是否能整除3來判斷
我們可以把符合條件的數字分成重複的和不重複的, 然後不重複的數字可以先不管 通過重複的數字和可以根據表格可以看出儅出現 一個重複數字的時候,
比如說儅重複數字為 1個時,可能出現的情況是 0 1 2 3 4 5 6 7 8 9 有4個數(mod 3 = 0 ) 有3個數(mod 3 = 1) 有3個數(mod 3 = 2)
比如說儅重複數字為 2個時,可能出現的情況是 00 11 22 33 44 55 66 77 88 99 有4個數(mod 3 = 0 ) 有3個數(mod 3 = 1) 有3個數(mod 3 = 2)
比如說儅重複數字為 3個時,可能出現的情況是000 111 222 333 444 555 666 777 888 999 所有的情況都是 3*x 所以全部都是能整除的 有10個數(mod 3 = 0 ) 有0個數(mod 3 = 1) 有0個數(mod 3 = 2)
所以只有重複數字為 3個 時, 才有可能出現八個素數的情況 namo 假設答案是五位數 裏面選兩個數不重複 其他為重複的, 然後重複的數字需要從 0 1 2 開始才有可能有八個 且不能是結尾數字,
所以就在前四位數字裏面選擇一位為 不重複數字 就有四種情況
{1, 0, 0, 0, 1},
{0, 1, 0, 0, 1},
{0, 0, 1, 0, 1},
{0, 0, 0, 1, 1} 1 代表非重複數字, 0 代表重複數字
然後非重複數字用兩位數字填上, 重複數字由 0 1 2 開始枚舉是否符合素數條件
答案是 六位數的話, 就在前面五位數字選兩個做非重複數字 於是有十種情況, 以此類推,
{1, 1, 0, 0, 0, 1},
{1, 0, 1, 0, 0, 1},
{1, 0, 0, 1, 0, 1},
{1, 0, 0, 0, 1, 1},
{0, 1, 1, 0, 0, 1},
{0, 1, 0, 1, 0, 1},
{0, 1, 0, 0, 1, 1},
{0, 0, 1, 1, 0, 1},
{0, 0, 1, 0, 1, 1},
{0, 0, 0, 1, 1, 1}
跑一邊以後 發現 答案就是六位數
#include <bits/stdc++.h> using namespace std; using namespace std::chrono; #define _for(i,a,b) for(int i = (a); i < (b); i++) #define _rep(i,a,b) for(int i = (a); i <= (b); i++) #define ll long long #define all(v) v.begin(), v.end() ll gcd(ll a, ll b) {return (!b)? a : gcd(b, a%b);} ll lcm(ll a, ll b) {return a/gcd(a, b)*b;} int is_prime(int x) { if(x < 2) return 0; int q = sqrt(x); _rep(i,2,q) if(x%i == 0) return 0; return 1; } int get5digitPatterns[4][5] = { {1, 0, 0, 0, 1}, {0, 1, 0, 0, 1}, {0, 0, 1, 0, 1}, {0, 0, 0, 1, 1} }; int get6digitPatterns[10][6] = { {1, 1, 0, 0, 0, 1}, {1, 0, 1, 0, 0, 1}, {1, 0, 0, 1, 0, 1}, {1, 0, 0, 0, 1, 1}, {0, 1, 1, 0, 0, 1}, {0, 1, 0, 1, 0, 1}, {0, 1, 0, 0, 1, 1}, {0, 0, 1, 1, 0, 1}, {0, 0, 1, 0, 1, 1}, {0, 0, 0, 1, 1, 1} }; int getLenOfArray(int *b) {return (sizeof(b)/sizeof(b[0]));} int fillPattern(int *b, int repeatingnumber,int n) { int res = 0; _for(i,0,n) { res *= 10; res += (b[i] == -1 ? repeatingnumber : b[i]); // 重複的數字填上, 其他照常 //cout << "res = " << res << "\n"; } return res; } void pe51() { int a[10][10] = {}, row, col, n1; _for(i,11,1000) {// not repeating number if(i > 100) { _for(i,0,10) _for(j,0,6) a[i][j] = get6digitPatterns[i][j]; row = 10, col = 6; } else { _for(i,0,4) _for(j,0,5) a[i][j] = get5digitPatterns[i][j]; row = 4, col = 5; } //_for(i1,0,row) {_for(j1,0,col) cout << a[i1][j1] << " "; cout << " ,a\n";} _for(j,0,row) { int n = i; int b[10] = {}; //_for(i1,0,col) cout << b[i1] << " "; cout << " , init b\n"; cout << row << " = row\n"; for(int k = col-1; k >= 0; k--) { // the starting repeating number(must 0 1 2 otherwise no possible 8 number family) if(a[j][k] == 1) b[k] = n%10, n /= 10; else b[k] = -1; } //_for(i1,0,col) cout << b[i1] << " "; cout << " ,b\n"; //_for(i1,0,col) cout << a[j][i1] << " "; cout << " ,a\n"; _for(k,0,3) { if(k == 0 and b[0] == -1) continue; // first number is 0, skip int x = fillPattern(b, k, col); //_for(i1,0,10) cout << b[i1] << " "; cout << " dsdsd, x= " << x << "\n"; //return; if(is_prime(x)) { int cnt = 1; //cout << " , x= " << x << "\n"; _for(repeatnumber, k+1, 10) if(is_prime(fillPattern(b, repeatnumber, col))) cnt++; if(cnt == 8) { cout << x << "\n"; _for(repeatnumber, k+1, 10) if(is_prime(fillPattern(b, repeatnumber, col))) cout << fillPattern(b, repeatnumber, col) << " "; cout << "\n"; //return; } } } } } return; } int main() { // ios::sync_with_stdio(false), cin.tie(nullptr); // taskA(); // taskpe27(); // taskA(); cout << "start \n"; auto start = high_resolution_clock::now(); pe51(); auto end = high_resolution_clock::now(); auto duration = duration_cast<microseconds>(end - start); cout << " cost = " << duration.count()/1000000 << "s\n"; cout << "end\n"; // pe27(); return 0; }
start 121313 222323 323333 424343 525353 626363 828383 929393 cost = 0s end