【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 }
【2018 China Collegiate Programming Contest Final (CCPC-Final 2018)】L. Ultra Weak Goldbach's Conjecture

 

posted @ 2019-06-18 21:11  KingSann  阅读(256)  评论(0编辑  收藏  举报