• 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}..

        因为很多情况会产生相同的lcm,所以只考虑max{pi},因为max不同则lcm一定不同,即问题转化为求方案数满足:

            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] }

      则答案为sigma{ f[tot][i] }

    【代码】

     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 }
  • 相关阅读:
    关于Java 下 Snappy压缩存文件
    英文分词和中文分词
    vuex requires a Promise polyfill in this browser
    Vue 中 export default 和 module.exports
    Linux 进程以及多线程的支持
    mysqldump
    linux磁 盘分区 挂载
    ubuntu16.04挂载windows NTFS磁盘方法
    Linux服务管理 systemctl命令详解
    nextcloud 安装
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5302772.html
Copyright © 2020-2023  润新知