[bzoj1025][SCOI2009]游戏
题意:可以转化为:把n分成任意个数,这些数的lcm有多少种 n<=1000
所以把质数筛出来,然后f[i][j]表示前i个质数用j点体力有多少种答案
枚举i,枚举j,枚举选k个,f[i][j]+=f[i-1][j-s[i]*k]
这样就转化为了一道01背包
复杂度n^1.5*logn
#include<iostream> #include<cstdio> #include<algorithm> #define ll long long using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} return x*f; } bool b[1005]; ll f[1005][1005],s[1005],n,cnt=0; int pow(int x,int p) { if(p==0)return 0; int sum=1; for(int i=x;p;p>>=1,i=i*i) if(p&1) sum=sum*i; return sum; } int main() { for(int i=2;i<=1000;i++) { if(!b[i]) s[++cnt]=i; for(int j=1;j<=cnt&&s[j]*i<=1000;j++) { b[s[j]*i]=1;if(i%s[j]==0)break; } } n=read();f[0][0]=1;int i; for(i=1;i<=cnt;i++) if(s[i]<=n) { for(int j=0;j<=n;j++) { for(int k=0;k<=n;k++) { int x=pow(s[i],k); if(x<=j) { f[i][j]+=f[i-1][j-x]; // cout<<i<<" "<<j<<" "<<k<<" "<<f[i][j]<<endl; } else break; } } } else break;ll ans=0; for(int j=1;j<=n;j++)ans+=f[i-1][j]; cout<<ans+1; return 0; }
FallDream代表秋之国向您问好!
欢迎您来我的博客www.cnblogs.com/FallDream