题意:
刚开始说哥德巴赫猜想任意一个大于2的偶数都能被两个质数相加,然后又说大于5的奇数能被3个质数相加。现在问你任意大于11的数,是否能用6个质因数相加,如果不能输出impossible否则输出6个数字。
思考:
刚开始说的2个定理,我总感觉会用到…把2的和5的联合起来,实际上不是按这来做的。对于任意一个>11的要表示成6个数字,那为何我不先把其中4个给用掉呢,然后就变成2个数相加即可,也就是变成了哥德巴赫,但是剩余的数需要是偶数。很明显如果n是奇数那么先减去2 2 2 3,如果是偶数先减去2 2 2 2。剩下的就直接哥德巴赫就行了。对了,由于n很大,直接check会太慢,用了rabin快速判断素数。同时用了快速乘,快速幂里面的乘法也用快速乘。因为模数是1e9+7,如果两个1e9+5相乘,就炸longlong了,所以快速成能保证不炸。为什么以前%1e9+7不会炸呢,因为long long最大可以存9e18,所以不会炸。这题同样是%1e9+7为啥炸了呢,因为rabin里面有个地方不是%1e9+7而是%x,所以有可能炸。
代码:
int T,n,m,k;
int va[M];
int pri[M],st[M],cnt;
int ksc(int a,int b,int p)
{
// int sum = 0;
// while(b)
// {
// if(b&1) sum = (sum+a)%p;
// a = (a+a)%p;
// b >>= 1;
// }
// return sum;
return (a*b-(int)(a/(long double)p*b+1e-3)*p+p)%p;
}
int ksm(int a,int b,int p)
{
int sum = 1;
while(b)
{
if(b&1) sum = ksc(sum,a,p);
a = ksc(a,a,p);
b >>= 1;
}
return sum;
}
bool rabin(int x)
{
if(x==2) return true;
if(x<2||!(x&1)) return false;
int a = 0,b = x-1;
while(!(b&1)) a++,b>>=1;
srand(time(NULL));
for(int i=1;i<=5;i++)
{
int t = rand()%(x-2)+2;
int now = ksm(t,b,x),pre = now;
for(int j=1;j<=a;j++)
{
now = ksc(now,now,x);
if(now==1&&pre!=1&&pre!=x-1) return false;
pre = now;
}
if(now!=1) return false;
}
return true;
}
void init(int x)
{
st[1] = 1;
for(int i=2;i<=x;i++)
{
if(!st[i]) pri[++cnt] = i;
for(int j=1;pri[j]*i<=x;j++)
{
st[pri[j]*i] = 1;
if(i%pri[j]==0) break;
}
}
}
/*
当然也可以直接check一遍
bool check(int x)
{
int a = x,b = n-x;
for(int i=1;i<=cnt&&pri[i]<=b;i++)
{
if(pri[i]==b) return true;
if(b%pri[i]==0) return false;
}
return true; //这里为什么一定是true呢,因为一个大数,如果不是质数,他的因子一定在sqrt(x)之内,现在1e6之内都没有这个因子,所以他肯定是质数。当然了x最大是1e12,所以就看看1e6之内有没有就行了。
}
*/
signed main()
{
IOS;
init(1e6+5);
cin>>T;
for(int cs=1;cs<=T;cs++)
{
cin>>n;
cout<<"Case "<<cs<<": ";
if(n<=11)
{
cout<<"IMPOSSIBLE\n";
continue;
}
if(n&1)
{
n -= 9;
cout<<"2 2 2 3 ";
for(int i=1;i<=cnt&&pri[i]<=n;i++)
{
if(rabin(n-pri[i]))
{
cout<<pri[i]<<" "<<n-pri[i]<<"\n";
break;
}
}
}
else
{
n -= 8;
cout<<"2 2 2 2 ";
for(int i=1;i<=cnt&&pri[i]<=n;i++)
{
if(rabin(n-pri[i]))
{
cout<<pri[i]<<" "<<n-pri[i]<<"\n";
break;
}
}
}
}
return 0;
}
总结:
多多思考积累经验,把复杂的问题简单化,要多想想如何去转化成这样。