• BZOJ 1025: [SCOI2009]游戏 [置换群 DP]


    传送门


    题意:求$n$个数组成的排列变为升序有多少种不同的步数


    步数就是循环长度的$lcm$.....

    那么就是求$n$划分成一些数几种不同的$lcm$咯

    然后我太弱了这种$DP$都想不出来....

    通过枚举每个质因子的指数来求$lcm$

    $d[i][j]$表示前$i$个质因子当前和为$j$的方案数

    转移枚举质因子的指数

    但这样我们忽略了可以划分出$1$,所以统计答案时枚举$j$

    或者我们直接初始化$d[0][i]=1$

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int N=1005;
    typedef long long ll;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
        return x*f;
    }
    int n;
    int p[N];
    bool notp[N];
    void sieve(int n){
        for(int i=2;i<=n;i++){
            if(!notp[i]) p[++p[0]]=i;
            for(int j=1;j<=p[0]&&i*p[j]<=n;j++){
                notp[i*p[j]]=1;
                if(i%p[j]==0) break;
            }
        }
    }
    ll f[N][N];
    void dp(){
        f[0][0]=1;
        for(int i=1;i<=p[0];i++)
            for(int j=0;j<=n;j++){
                f[i][j]=f[i-1][j];
                for(int k=p[i];k<=j;k*=p[i])
                    f[i][j]+=f[i-1][j-k];
            }
        ll ans=0;
        for(int i=0;i<=n;i++) ans+=f[p[0]][i];
        printf("%lld",ans);
    }
    int main(){
        freopen("in","r",stdin);
        n=read();
        sieve(n);
        dp();
    }
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int N=1005;
    typedef long long ll;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
        return x*f;
    }
    int n;
    int p[N];
    bool notp[N];
    void sieve(int n){
        for(int i=2;i<=n;i++){
            if(!notp[i]) p[++p[0]]=i;
            for(int j=1;j<=p[0]&&i*p[j]<=n;j++){
                notp[i*p[j]]=1;
                if(i%p[j]==0) break;
            }
        }
    }
    ll f[N][N];
    void dp(){
        f[0][0]=1;
        for(int i=1;i<=n;i++) f[0][i]=1;
        for(int i=1;i<=p[0];i++)
            for(int j=0;j<=n;j++){
                f[i][j]=f[i-1][j];
                for(int k=p[i];k<=j;k*=p[i])
                    f[i][j]+=f[i-1][j-k];
            }
        printf("%lld",f[p[0]][n]);
    }
    int main(){
        freopen("in","r",stdin);
        n=read();
        sieve(n);
        dp();
    }
  • 相关阅读:
    JS中的constructor、prototype、__proto__的要点理解
    call、apply、bind的源码模拟
    js中的继承方式
    IPV6
    java8 instant localDateTime
    FileInputFormat 的实现之TextInputFormat
    Git服务器,仓库的hook监控
    Linux 开机启动图形界面,shell界面
    java操作Hbase
    Linux 下安装 storm
  • 原文地址:https://www.cnblogs.com/candy99/p/6479961.html
Copyright © 2020-2023  润新知