牛客挑戰賽 53 B
阿新 • • 發佈:2021-10-16
題目描述
你需要找到一個序列 \(A_1, A_2 \dots A_i\dots A_m\)
並且每個 $A_i 都為質數或者 \({1}\) 或者 \({0}\) 使得
\(\sum_{i = 1}^{m}{A_i}\)
對於每個詢問,你需要找到最小的 \({m}\)。
資料保證題目有解。
特別的是,如果 \({s=0}\) 那麼你也至少需要一個 \({0}\) 來填滿它。
資料範圍
\(1 \leq s\leq 10^7\)
solution
如果 \(s\) 是個偶數,根據哥德巴赫猜想,它一定可以分解為兩個質數的和的形式。
如果是奇數的話就有兩種可能,一個是它可以由 \(2\) 和另一個質數相加,這種直接 \(check(n - 2)\)
另一種是把奇數 \(-1\) 變為偶數,在將這個偶數按照上面分解。
線篩預處理個質數就好了。
code
/* work by:Ariel_ Sorce: Knowledge: Time: */ #include <iostream> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #define rg register using namespace std; const int MAXN = 1e7 + 5; int read(){ int x = 0,f = 1; char c = getchar(); while(c < '0'||c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') {x = x*10 + c - '0'; c = getchar();} return x*f; } int tot, pre[MAXN]; bool vis[MAXN]; void Pre() { for(int i = 2; i <= MAXN; i++) { if(vis[i] == 0) pre[tot++] = i; for(int j = 0; j <= tot, i * pre[j] <= MAXN; j++){ vis[pre[j] * i] = 1; if (i % pre[j] == 0)break; } } } signed main() { int T = read(); Pre(); while(T--) { int x = read(); if(x == 0) {cout<<"1\n0 = 0\n";continue;} if(x == 1) {cout<<"1\n1 = 1\n";continue;} if(!vis[x]){cout<<"1\n"<<x<<" = "<<x<<"\n";continue;} int opt = 1; if(x & 1) { int fag = 0, z, w; if(!vis[x - 2]) { cout<<"2\n"; cout<<"2 + "<<x - 2<<" = "<<x<<"\n"; continue; } cout<<"3\n"<<"1 + "; x--, opt = 0; } else cout<<"2\n"; for (int i = 3; i < x; i++) if (!vis[i] && !vis[x - i]){printf("%d + %d", i, x - i); break;} if(opt == 0) printf(" = %d\n", x + 1); else printf(" = %d\n", x); } return 0; }