【BZOJ 1025】[SCOI2009]游戏 置换+dp

来源:互联网 发布:知止而行的例子 编辑:程序博客网 时间:2024/05/21 10:58

又是一个套路。。。。

我们把每一种关系当作一条边,那么最后会形成一个n个点n条边的图,每出现一个环就是循环了,所以问题就是求这些环的最小公倍数的种类,手画一下会很容易发现,这个图由于是n个点n条边,所以至少出现一个环,而且环与环不会相交,也就是说,∑环的边数<=n (但是环或者单点有多个)最终问题转化为求和<=n的数的最小公倍数的种类,dp

#include<cstdio>#include<cstring>#include<iostream>#define maxn 1020#define LL long longusing namespace std;int n,cnt,p[maxn],vis[maxn];LL f[maxn][maxn];void make(){for(int i=2;i<maxn;i++){if(!vis[i])p[++cnt]=i;for(int j=1;j<=cnt&&i*p[j]<maxn;j++){vis[i*p[j]]=1;if(!i%p[j])break;}}}int main(){make();scanf("%d",&n);f[0][0]=1;for(int i=1;i<=cnt;i++){for(int j=0;j<=n;j++){f[i][j]=f[i-1][j];for(int k=p[i];k<=j;k*=p[i])f[i][j]+=f[i-1][j-k];}}LL ans=0;for(int i=0;i<=n;i++)ans+=f[cnt][i];cout<<ans;return 0;}


0 0
原创粉丝点击