bzoj 1025 [SCOI2009]游戏(置换群,DP)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 1025 [SCOI2009]游戏(置换群,DP)相关的知识,希望对你有一定的参考价值。

 

【题目链接】

 

    http://www.lydsy.com/JudgeOnline/problem.php?id=1025

 

【题意】

 

    给定n,问1..n在不同的置换下变回原序列需要的不同排数有多少种。

 

【思路】

 

    对于一个置换,如果分解后的到的循环长度为

        A1,A2,A3…

    则答案为lcm(A1,A2…)的不同种数,即有多少个不同的lcm满足:

        A1+A2+A3+…=n

        lcm=lcm(A1,A2,A3…)

    对于A[1..]的lcm,

        lcm=a1^max{p1}*a2^max{p2}..

    只考虑max{pi},即转化为求方案数满足:

        a1^max{p1}*a2^max{p2}<=n

  设f[i][j]表示前i个质数和为j的方案,则有:

        f[i][j]=f[i-1][j]+sigma{ f[i-1][j-p[i]^k] }

 

【代码】

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 using namespace std;
 5 
 6 typedef long long ll;
 7 const int N = 1e3+5;
 8 
 9 int n;
10 int p[N],su[N],tot; ll f[N][N];
11 
12 void get_prime()
13 {
14     for(int i=2;i<=n;i++) if(!su[i]) {
15         p[++tot]=i;
16         for(int j=i*i;j<=n;j+=i) su[j]=1;
17     }
18 }
19 int main()
20 {
21     scanf("%d",&n);
22     get_prime();
23     f[0][0]=1;
24     for(int i=1;i<=tot;i++) {
25         for(int j=0;j<=n;j++) {
26             f[i][j]=f[i-1][j];
27             for(int k=p[i];k<=j;k*=p[i])
28                 f[i][j]+=f[i-1][j-k];
29         }
30     }
31     ll ans=0;
32     for(int i=0;i<=n;i++) ans+=f[tot][i];
33     printf("%lld",ans);
34     return 0;
35 }

 

以上是关于bzoj 1025 [SCOI2009]游戏(置换群,DP)的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ1025 [SCOI2009]游戏

bzoj1025: [SCOI2009]游戏(DP)

bzoj1025: [SCOI2009]游戏

BZOJ1025: [SCOI2009]游戏

bzoj 1025[SCOI2009]游戏 - 背包dp

bzoj1025 [SCOI2009]游戏——因数DP