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;
}

猜你喜欢

转载自www.cnblogs.com/Narh/p/9143943.html