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

  • 相关阅读:
    课堂作业04 2017.10.27
    课程作业 03 动手动脑 2017.10.20
    课程作业 03 2017.10.20
    HDU 3974 Assign the task
    POJ 2155 Matrix
    POJ 2481 Cows
    HDU 3038 How Many Answers Are Wrong
    CS Academy Array Removal
    POJ_1330 Nearest Common Ancestors LCA
    CF Round 427 D. Palindromic characteristics
  • 原文地址:https://www.cnblogs.com/cutemush/p/12133940.html
Copyright © 2011-2022 走看看