又是一个套路。。。。
我们把每一种关系当作一条边,那么最后会形成一个n个点n条边的图,每出现一个环就是循环了,所以问题就是求这些环的最小公倍数的种类,手画一下会很容易发现,这个图由于是n个点n条边,所以至少出现一个环,而且环与环不会相交,也就是说,∑环的边数<=n (但是环或者单点有多个)最终问题转化为求和<=n的数的最小公倍数的种类,dp
#include<cstdio>
#include<cstring>
#include<iostream>
#define maxn 1020
#define LL long long
using 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;
}