bzoj1025(SCOI2009)游戏——唯一分解的思路与应用
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1025
可以认为对应的值之间连边,就连成了一个有一个或几个环的图。列数就是每个环里点数的lcm的和+1。
所以问题转化为和为n的数列的lcm种类数。
然后就看了TJ。这个人写得真的很好。https://www.cnblogs.com/phile/p/4473192.html
关键点就是将思路改成“判断这个x是不是可行(是否可以是和为n的数的lcm,因为可以有任意个1,所以也就是是否可以是和<=n的数的lcm)”。
从这个角度入手,每一个x都可以唯一分解,然后lcm是它的那些数就是一个或几个质数的幂(不能把一个质数的幂拆开,那样lcm就会小一些);
只要某一种幂的组合的和<=n就行了。于是考虑最小的和,发现是……(详见那个人的博客)
可知质数最大不超过n。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int N=1005; int n,pri[N],cnt; long long ans,dp[N][N]; bool vis[N]; void init() { for(int i=2;i<=n;i++) { if(!vis[i])pri[++cnt]=i; for(int j=1;j<=cnt&&i*pri[j]<=n;j++) { vis[i*pri[j]]=1; if(i%pri[j]==0)break; } } } int main() { scanf("%d",&n); init();dp[0][0]=1; for(int i=1;i<=cnt;i++) { for(int k=0;k<=n;k++)dp[i][k]=dp[i-1][k];/////还可以不用这个质数! for(int j=pri[i];j<=n;j*=pri[i]) for(int k=j;k<=n;k++) dp[i][k]+=dp[i-1][k-j]; } for(int i=0;i<=n;i++)ans+=dp[cnt][i]; printf("%lld",ans); return 0; }