BZOJ1025 [SCOI2009]游戏

首先很显然的是,对于多组置换他们的周期就是置换长度的lcm

且长度之和等于n

而这些置换长度可能是多个px^ax的乘积,由于都是正数且都大于1所以乘积肯定比加和大

性质:若p1^a1+p2^a2+...+pm^am<=n①,则ans=p1^a1*p2^a2*..*pm^am②是n的一个可行答案。

如果①式大于n的话那么长度之和显然也会大于n,所以当且仅当①式小于等于n时有解

而且我们通过质因数次幂的枚举可以保证不会枚举重复且枚举全部。

这就转化为在①式条件下求(a1,a2,a3...an)的种类。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 long long f[1005][1005],ans;
 4 int v[1005],cnt,p[1005],n;
 5 void pri()
 6 {
 7     for(int i=2;i<=1000;++i)
 8     {
 9         if(!v[i])p[++cnt]=i;
10         for(int j=1;j<=cnt&&i*p[j]<=1000;++j)
11         {
12             v[i*p[j]]=1;if(i%p[j]==0)break;
13         }
14     }
15 }
16 int main()
17 {
18     scanf("%d",&n);
19     pri();f[0][0]=1;
20     for(int i=1;i<=cnt;++i)
21     {
22         for(int j=0;j<=n;++j)f[i][j]=f[i-1][j];
23         for(int j=p[i];j<=n;j*=p[i])
24         {
25             for(int k=0;k+j<=n;++k)
26             f[i][j+k]+=f[i-1][k];
27         }
28     }
29     for(int i=0;i<=n;++i)ans+=f[cnt][i];
30     printf("%lld\n",ans);
31     return 0;
32 }

 

posted @ 2018-01-20 10:29  大奕哥&VANE  阅读(126)  评论(0编辑  收藏  举报