NC20271 游戏(数学+dp)

这种置换题一般都与图论结合

这题也不例外,显然绕一圈就是一个环

而使得全部回到原位就是每个环的lcm

在不考虑自环的情况下,我们求的就是大小为n,进行集合划分,求每个集合得lcm

这里又要进行一步转化,由于当每个集合互质的时候,lcm每次都不相同,我们只要枚举质数做完全背包就能求出方案数

假设一个集合中并不是质数的幂次,那么他其实对应的就是另一种质数幂次的方案,所以只要枚举质数就能求解所有答案

现在有自环,因此大小不一定为n,只要从1-n所有情况求一边和即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int N=2e5+10;
const int mod=1e9+7;
ll f[N],st[N];
int cnt,primes[N];
void init(int n){
    int i;
    for(i=2;i<=n;i++){
        if(!st[i]){
            primes[++cnt]=i;
        }
        for(int j=1;primes[j]*i<=n;j++){
            st[i*primes[j]]=1;
            if(i%primes[j]==0)
                break;
        }
    }
}
int main(){
    ios::sync_with_stdio(false);
    int n;
    cin>>n;
    init(n);
    int i;
    f[0]=1;
    for(i=1;i<=cnt;i++){
        int x=primes[i];
        for(int k=n;k>=primes[i];k--){
            for(int j=x;j<=k;j*=x){
                if(f[k-j]!=-0x3f3f3f3f){
                    f[k]+=f[k-j];
                }
            }
        }
    }
    ll ans=0;
    for(i=1;i<=n;i++)
        ans+=f[i];
    cout<<ans+1<<endl;
}
View Code
没有人不辛苦,只有人不喊疼
原文地址:https://www.cnblogs.com/ctyakwf/p/14584521.html