[bzoj1025][SCOI2009]游戏【dp】

【题目链接】
  http://www.lydsy.com/JudgeOnline/problem.php?id=1025
【题解】
  ans=lcm(l1..ln)
  其中 li 为每个变换的循环长度。
  接下来就可以dp了
  记 f[i][j] 表示考虑了前i个素数,使用了不多于j个数字的方案数。
  转移就是f[i][j]=kf[i1][jPik]+f[i1][j]
 

/* --------------
    user Vanisher
    problem bzoj-1025
----------------*/
# include <bits/stdc++.h>
# define    ll      long long
# define    N       1010
using namespace std;
ll read(){
    ll tmp=0, fh=1; char ch=getchar();
    while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();}
    while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();}
    return tmp*fh;
}
ll n,f[N][N],p[N],pnum;
bool fp[N];
int main(){
    n=read();
    fp[1]=true;
    for (ll i=2; i<=n; i++)
        if (fp[i]==false){
            p[++pnum]=i;
            for (ll j=i+i; j<=n; j+=i)
                fp[j]=true;
        }
    for (ll i=0; i<=n; i++)
        f[0][i]=1;
    for (ll i=1; i<=pnum; i++){
        f[i][p[i]]=1;
        for (ll j=p[i]+1; j<=n; j++){
            for (ll k=p[i]; k<=j; k*=p[i])
                f[i][j]+=f[i-1][j-k];
    //      f[i][j]=max(f[i][j],f[i][j-1]);
        } 
        for (ll j=0; j<=n; j++)
            f[i][j]+=f[i-1][j];
    }
    printf("%lld\n",f[pnum][n]);    
    return 0;
}
posted @ 2018-03-02 08:25  Vanisher  阅读(87)  评论(0编辑  收藏  举报