这种置换题一般都与图论结合
这题也不例外,显然绕一圈就是一个环
而使得全部回到原位就是每个环的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; }