Fancy is learning mathematics recently. He's already mastered the use of multiplication and addition days before, so today he's going to learn prime number.
After reading the learning material, he's been asked to complete a simple test. He's been given an integer X larger than 1, using multiplication, addition and at most 3 prime numbers, how many ways could he get the answer as X exactly?
Since that Fancy is a new learner of mathematics, he's still not familiar with brackets. So in the calculation, the addition is always performed after multiplication.
Input
There will be multiple test cases. Each test case contains a single integer X (1 < X ≤ 80000) in one line.
Output
For each test case, please calculate the number of ways which Fancy could get the answer as X. Since that the number of ways might be large, please output it modulo 1000000007.
Sample Input
5 10 8
Sample Output
2 4 4
Hint
In the 3rd case, 8 = 2 * 2 * 2 = 2 + 2 * 3 = 2 + 3 + 3 = 3 + 5, so the answer is 4.
比赛的时候为了想不计算重复,想了各种方法,比较绕,时间再多一点或许就过了。做距离的那个题时候,不知道为什么死在精度上了。耽误了时间。主要还是暴力。
一个数由最多三个素数组成,只能用*或+
(1)当由一个素数组成的时候,看其本身是否是素数、
(2)当由两个素数组成的时候,暴力一个素数求另一个素数,有+和*两种情况。
(3)当由三个素数组成的时候,如果是三个素数相乘,暴力可以得到解决。
如果是三个素数采用 a*b + c的方式,我们暴力c,我们把一个数由两个素数相乘的情况先求出来,sum[n]+=(b[n-c]),暴力c。
如果是三个素数采用相加的形式即 n = a + b + c; H:求两个素数(两个素数不相同)组成的和,然后再加入第三个素数.这时候会产生重复,记录一下一个数的情况数:H 想着办法去重就可以了。可以通过: <1>假设a,b,c完全相同很容易实现。<2>假设有两个相同,则枚举这个相同的。 <3>如果三个完全不同,由H: :H 暴力肯定会产生不满足的情况或重复的情况。所谓不满足的情况就是产生了由两个相同的素数,从s[n]中减去先前枚举出来(<2>中)的两个相同的情况。然后/3 就是三个完全不同的数。<1>+<2>+<3>得出三个素数相加情况。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define N 80010
#define mod 1000000007
using namespace std;
bool ch[N];
int a[N],one[N],two_a[N],two_b[N],three[N],sum[N];
int key[N],two_one[N],b[N];
int main()
{
// freopen("data.in","w",stdout);
memset(ch,true,sizeof(ch));
ch[1]=false;
for(int i=2;i<=80000;i++)
{
if(ch[i])
{
for(int j=2;i*j<=80000;j++)
{
ch[i*j] = false;
}
}
}
int Top =0;
for(int i=2;i<=80000;i++)
{
if(ch[i])
{
a[Top++] = i;
}
}
memset(one,0,sizeof(one));
for(int i=2;i<=80000;i++)
{
if(ch[i])
{
one[i] +=1;
}
}
memset(two_a,0,sizeof(two_a));
for(int i=2;i<=80000;i++)
{
for(int j = 0;j<=Top-1;j++)
{
int x = a[j];
int y = i-a[j];
if(x<=y&&ch[y])
{
two_a[i]=(two_a[i]+1)%mod;
}else if(x>y)
{
break;
}
}
}
memset(two_b,0,sizeof(two_b));
for(int i=2;i<=80000;i++)
{
for(int j=0;j<=Top-1;j++)
{
int x = a[j];
if(i%x!=0)
{
continue;
}
int y = i/x;
if(x<=y&&ch[y])
{
two_b[i]=(two_b[i]+1)%mod;
}else if(x>y)
{
break;
}
}
}
memset(three,0,sizeof(three));
for(int i=2;i<=80000;i++)
{
for(int j=0;j<=Top-1;j++)
{
int x = a[j];
if(x*x*x>i)
{
break;
}
for(int u = j;u<=Top-1;u++)
{
int y = a[u];
if(x*y*y>i)
{
break;
}
if(i%(x*y)!=0)
{
continue;
}
int z = i/(x*y);
if(z<y)
{
break;
}
if(ch[z])
{
three[i]=(three[i]+1)%mod;
}
}
}
}
memset(two_one,0,sizeof(two_one));
for(int i=2;i<=80000;i++)
{
for(int j=0;j<=Top-1;j++)
{
int x = a[j];
if(i<=2*x)
{
break;
}
int y = i - 2*x;
if(y!=x&&ch[y])
{
two_one[i]+=1;
}
}
}
memset(sum,0,sizeof(sum));
for(int i=0;i<=Top-1;i++)
{
for(int j=i+1;j<=Top-1;j++)
{
if(a[i]+a[j]>80000)
{
break;
}
sum[a[i]+a[j]]+=1;
}
}
memset(key,0,sizeof(key));
for(int i=2;i<=80000;i++)
{
for(int j=0;j<=Top-1;j++)
{
int x = i + a[j];
if(x<=80000)
{
key[x] = (key[x]+sum[i]);
}
}
}
for(int i=2;i<=80000;i++)
{
key[i]=(key[i]-two_one[i])/3;
key[i]+=(two_one[i]);
}
for(int i=2;i<=80000;i++)
{
if(i>=6&&i%2==0)
{
three[i]=(three[i]+two_a[i-2])%mod;
}else if(i>=7&&i%2)
{
three[i]=(three[i]+key[i])%mod;
if(i%3==0&&ch[i/3])
{
three[i]+=1; //三个素数全部相等
}
}
}
for(int i=2;i<=80000;i++)
{
for(int j = 0;j<=Top-1;j++)
{
int x = a[j];
if(i<=x)
{
break;
}
three[i]=(three[i]+two_b[i-x])%mod;
}
}
int n;
while(scanf("%d",&n)!=EOF)
{
int res = (((one[n]+two_a[n])%mod+two_b[n])%mod+three[n])%mod;
printf("%d\n",res);
}
return 0;
}