您的位置:首页 > 其它

Light OJ 1298 One Theorem, One Year (DP)

2016-02-17 11:57 471 查看
解析:

欧拉函数公式:phi(n)=n(1-1/p1)(1-1/p2)(1-1/p3)...(1-1/pk),其中pi为n的素因子。

有了这个公式 ,我们只需要求出对应的数字的和就好了。

dp[i][j] = 用前i+1个素数组成j个素数积的各数字的和。(有点绕……

状态转移:dp[i][j] = prime[i]*(dp[i][j-1]+dp[i-1][j-1])。

:

[code]#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>

using namespace std;
typedef long long LL;
const LL MOD = 1e9+7;

int n,m,pl,prime[1005];
LL dp[505][505];

LL modPow(LL a,LL b){
LL res = 1;
while(b){
if(b&1) res = (res*a)%MOD;
a = (a*a)%MOD;
b >>= 1;
}
return res;
}

void makePrime(){
static bool isPrime[5005];
int i,j;
pl = 0;
fill(isPrime,isPrime+5005,true);
for(i = 2;i < 5005;i++){
if(isPrime[i]){
prime[pl++] = i;
for(j = i;j < 5005;j+=i) isPrime[j] = false;
}
}
}
LL dfs(int i,int j){
if(i >= j) return 0;
if(i == 0) return modPow(2,j);
if(dp[i][j]!=-1) return dp[i][j];
dp[i][j] = (prime[i]*(dfs(i-1,j-1)+dfs(i,j-1)))%MOD;
return dp[i][j];
}
int main(){
int i,j,cas,T;
scanf("%d",&cas);
makePrime();
memset(dp,-1,sizeof(dp));
for(T = 1;T <= cas;T++){
scanf("%d%d",&m,&n);
LL res = dfs(n-1,m);
for(i = 0;i < n;i++) res = ((res*(prime[i]-1)%MOD)*modPow(prime[i],MOD-2)%MOD+MOD)%MOD;
printf("Case %d: %lld\n",T,res);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: