【2018 China Collegiate Programming Contest Final (CCPC-Final 2018)】L. Ultra Weak Goldbach's Conjecture
题目描述
给定整数 $x$,判断它是否能写成 $6$ 个素数之和的形式
如果可以,给出一种构造方式,否则输出 $\text{IMPOSSIBLE}$
数据范围:$1 \le x \le 10^{12}$
题解
由于哥德巴赫猜想在 $[1,10^{12}]$ 成立,因此可以直接考虑构造出 $x$ 较小的部分
如果 $x$ 是奇数,则把 $x$ 写成 $3p+2+y+z$ 的形式,其中 $p,y,z$ 是素数
如果 $x$ 是偶数,则把 $x$ 写成 $4p+y+z$ 的形式,其中 $p,y,z$ 是素数
那么 $p$ 分别小于 $\frac{x}{3}$ 和 $\frac{x}{4}$ 即可,那么 $y+z$ 不会很大,可以 $O((y+z)^2)$ 预处理拆分结果
代码
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef unsigned long long ull; 5 const int pr[]={2,3,5,7,11,23,43,79}; 6 const int M=(1<<8)-1; 7 8 mt19937 RandEngine(chrono::steady_clock::now().time_since_epoch().count()); 9 ll RandInt(ll L,ll R){return uniform_int_distribution<ll>(L,R)(RandEngine);} 10 11 ll Mx=0; 12 13 ll gcd(ll a,ll b) 14 { 15 if(!a||!b) return a|b; 16 #define ctz __builtin_ctzll 17 int shift=ctz(a|b); 18 b>>=shift; 19 while(a) 20 { 21 a>>=ctz(a); 22 if(a<b) 23 swap(a,b); 24 a-=b; 25 } 26 return b<<shift; 27 #undef ctz 28 } 29 30 ull Mul(ull a,ull b,ull P) 31 { 32 ull c=(ll)a*b-(ll)((ull)((long double)a*b/P))*P; 33 return (c+P)%P; 34 } 35 36 ll ksm(ll a,ll b,ll P) 37 { 38 ll ret=1; 39 for(;b;b>>=1,a=Mul(a,a,P)) 40 if(b&1) 41 ret=Mul(ret,a,P); 42 return ret; 43 } 44 45 bool Miller_Rabin(ll n) 46 { 47 if(n==2||n==3||n==5||n==7||n==11||n==23||n==43||n==79) 48 return true; 49 if(~n&1) 50 return false; 51 for(int p:pr) 52 { 53 ll t=n-1,c=0; 54 while(~t&1) 55 t>>=1,++c; 56 ll pw=ksm(p,t,n); 57 if(pw==1) 58 continue; 59 bool f=(pw==n-1); 60 while(c) 61 { 62 pw=Mul(pw,pw,n); 63 f|=(pw==n-1); 64 --c; 65 if(pw==1&&!f) 66 return false; 67 } 68 if(pw!=1||!f) 69 return false; 70 } 71 return true; 72 } 73 74 75 76 const int mod = 1e9 + 7; 77 78 ll pw(ll a, ll b) { 79 ll r = 1; 80 for( ; b ; b >>= 1, a = a * a % mod) { 81 if(b & 1) { 82 r = r * a % mod; 83 } 84 } 85 return r; 86 } 87 88 ll getinv(ll n) { 89 return pw(n, mod - 2); 90 } 91 92 const int N = 7010; 93 int vis[N], pri[N], tot; 94 int a[N]; // x = a[x] + (x - a[x]) 95 int isp[N]; 96 97 void init(int n) { 98 for(int i = 2 ; i <= n ; ++ i) { 99 if(!vis[i]) { 100 pri[++ tot] = i; 101 isp[i] = 1; 102 for(int j = i ; j <= n ; j += i) { 103 vis[j] = 1; 104 } 105 } 106 } 107 for(int i = 2 ; i <= n ; ++ i) { 108 for(int j = 2 ; j <= i ; ++ j) { 109 if(i - j >= 2 && isp[j] && isp[i - j]) { 110 a[i] = j; 111 break; 112 } 113 } 114 } 115 } 116 117 #define isitp Miller_Rabin 118 119 void runprog() { 120 ll n; scanf("%lld", &n); 121 if(n == 12) { 122 puts("2 2 2 2 2 2"); 123 } else if(n == 14) { 124 puts("2 2 2 2 3 3"); 125 } else if(n <= 11) { 126 puts("IMPOSSIBLE"); 127 } else if(n & 1) { 128 ll p = n / 3 - 1; 129 while(p >= 2 && !isitp(p)) { 130 -- p; 131 } 132 -- p; 133 while(p >= 2 && !isitp(p)) { 134 -- p; 135 } 136 ll res = n - 2 - p * 3; 137 printf("%lld %lld %lld %d %d %d\n", p, p, p, 2, a[res], res - a[res]); 138 } else { 139 ll p = n / 4 - 1; 140 while(p >= 2 && !isitp(p)) { 141 -- p; 142 } 143 -- p; 144 while(p >= 2 && !isitp(p)) { 145 -- p; 146 } 147 ll res = n - p * 4; 148 printf("%lld %lld %lld %lld %d %d\n", p, p, p, p, a[res], res - a[res]); 149 } 150 } 151 152 int main() { 153 init(N - 1); 154 int t; scanf("%d", &t); 155 while(t --) { 156 static int T = 0; 157 printf("Case %d: ", ++ T); 158 runprog(); 159 } 160 }