zoukankan      html  css  js  c++  java
  • 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] }

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=1000;
    int n;
    int prime[N],tot;
    bool isprime[N+1];
    void init()
    {
    memset(isprime,true,sizeof(isprime));
    for(int i=2;i<=n;i++)
    {
    if(isprime[i]) prime[++tot]=i;
    for(int j=1;j<=tot&&i*prime[j]<=n;j++)
    {
    isprime[i*prime[j]]=false;
    if(i%prime[j]==0) break;
    }
    }
    }
    long long f[200][N+1];
    int main()
    {
    scanf("%d",&n);
    init();
    for(int i=0;i<=tot;i++)
    f[i][0]=1;
    for(int i=1;i<=n;i++)
    f[0][i]=1;
    for(int i=1;i<=tot;i++)
    for(int j=1;j<=n;j++)
    {
    f[i][j]=f[i-1][j];
    for(int k=prime[i];k<=j;k*=prime[i])
    f[i][j]+=f[i-1][j-k];
    }
    printf("%lld",f[tot][n]);
    return 0;
    }

  • 相关阅读:
    C# 中的委托和事件
    sql笔记-group by 统计功能
    js,css小知识点记录
    sql小技巧
    《孙子兵法》总结
    .Net深复制、浅复制
    《君主论》
    php邮箱找回密码功能
    后台管理员账号不能同时登陆,以及登陆使对方强制下线功能
    好程序员应该读的30本书
  • 原文地址:https://www.cnblogs.com/cutemush/p/12133940.html
Copyright © 2011-2022 走看看