题意很简单,就是给你一个数x(x <= 80000),然后问你用最多三个素数(可以相同)加上两种运算符号(+ 和 *)有几种组合构成这个数x。
思路 : 因为x小于8W,2 ~ 8W中大概有8K左右个素数,配对方式大概有6中 : a 、a * b、 a * b * c、 a + b 、a + b * c 、 a + b + c。其实稍微考虑下就知道了复杂度和难点是在枚举a + b + c上。我的做法是先预处理出一个add数组(由两个不同的素数相加最多有几种方式), 然后O(n)枚举剩下一个,然后再去考虑下 a + a + b 和 a + a + a,就可以算出答案来了的。
给出代码 :
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MAXN = 80008;
const int mod = 1000000007;
int X,M;
bool Prime[MAXN],mul[MAXN];
int prime[MAXN],add[MAXN];
int Isprime(int x)
{
for (int i = 2;i * i <= x;i++)if (x % i == 0)
return 0;
return 1;
}
void init()
{
M = 0;
memset(add,0,sizeof(add));
memset(Prime,0,sizeof(Prime));
memset(mul,0,sizeof(mul));
for (int i = 2;i <= MAXN;i++)if (Isprime(i))
{
prime[++M] = i;
Prime[i] = 1;
}
for (int i = 1;i <= M;i++)
for (int j = i + 1;j <= M;j++)
{
if (prime[i] + prime[j] >= MAXN)break;
add[prime[i] + prime[j]] ++;
}
for (int i = 1;i <= M;i++)
for (int j = i ;j <= M;j++)
{
if ((LL)prime[i] * prime[j] >= MAXN)break;
mul[prime[i] * prime[j]] = 1;
}
}
// 这个函数主要是用来求a 、 a * b 、 a * b * c,返回值只可能是1 或 0
int get()
{
if (Prime[X])return 1;
if (mul[X])return 1;
int tmp = X;
int cnt = 0;
for (int i = 1;i <= M;i++)
{
while (tmp % prime[i] == 0 && tmp > 1)
{
tmp /= prime[i];
cnt ++;
if (cnt > 3)return 0;
}
if (tmp <= 1)
{
if (cnt <= 3)return 1;
else return 0;
}
}
}
int solve()
{
LL ans = get();
LL res = 0;
//求出 a + b 和 a + b * c
for (int i = 1;i <= M;i++)
{
int e = X - prime[i];
if (e <= 0)break;
if (Prime[e])res += (e == prime[i] ? 2 : 1);//注意a + a 这种情况
else ans += mul[e];
}
ans += res / 2;
ans %= mod;
res = 0;
//求出 a + b + c
for (int i = 1;i <= M;i++)
{
int e = X - prime[i];
if (e <= 0)break;
res += add[e];
}
for (int i = 1;i <= M;i++)
{
int e = X - prime[i];
if (e <= 0)break;
if (e % 2 == 0 && Prime[e/2])
{
if (e/2 == prime[i])continue;
ans ++;
res -= 1; //把一些重复枚举的删除
}
}
ans += (res/3);
ans %= mod;
if (X % 3 == 0 && Prime[X/3])ans++;//考虑a + a + a这种情况
return (int)(ans % mod);
}
int main()
{
init();
while (scanf("%d",&X) != EOF)
{
printf("%d\n",solve());
}
return 0;
}