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
Run result

 

posted @ 2021-08-20 00:57  163467  阅读(39)  评论(0编辑  收藏  举报