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

  • 相关阅读:
    js字符串String常用方法
    flexible.js结合rem实现移动端自适应布局
    Django API验证(令牌)
    错误堆栈信息
    JS Ajax异步请求发送列表数据后面多了[]
    根据后端传的时间前端js进行倒计时
    Vue select 下拉菜单
    centos 6.x 部署uwsgi+flask项目
    css 让背景图片不停旋转
    supervisor管理uwsgi
  • 原文地址:https://www.cnblogs.com/cutemush/p/12133940.html
Copyright © 2011-2022 走看看