zoukankan      html  css  js  c++  java
  • 【bzoj1025】【SCOI2009】【游戏】【dp】

    Description

    windy学会了一种游戏。对于1到N这N个数字,都有唯一且不同的1到N的数字与之相应。最開始windy把数字按顺序1,2。3。……,N写一排在纸上。

    然后再在这一排以下写上它们相应的数字。然后又在新的一排以下写上它们相应的数字。如此重复,直到序列再次变为1。2,3,……。N。

    如: 1 2 3 4 5 6 相应的关系为 1->2 2->3 3->1 4->5 5->4 6->6 windy的操作例如以下 1 2 3 4 5 6 2 3 1 5 4 6 3 1 2 4 5 6 1 2 3 5 4 6 2 3 1 4 5 6 3 1 2 5 4 6 1 2 3 4 5 6 这时,我们就有若干排1到N的排列,上例中有7排。如今windy想知道,对于全部可能的相应关系。有多少种可能的排数。

    Input

    包括一个整数,N。

    Output

    包括一个整数。可能的排数。

    Sample Input

    【输入例子一】
    3
    【输入例子二】
    10

    Sample Output

    【输出例子一】
    3
    【输出例子二】
    16

    HINT

    【数据规模和约定】

    100%的数据。满足 1 <= N <= 1000 。

    题解:首先能够发现这个变换是由几个子集合的轮换构成的。然后最后答案就是这几个轮换长度的最小公倍数+1

    然后轮换长度是从1-n的。那问题就变成了把n分成几个部分,然后这几个部分的最小公倍数的种类数。

    最小公倍数肯定就是一坨素因子加加乘乘。

    那么算出1-n有多少素因子。设f[i][j]表示用前i个素因子容量为j。

    直接背包好了。。

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int n,t,p[1001];
    long long ans,f[1001][1001];
    bool ff[1001];
    void get()
    {
        for(int i=2;i<=1000;i++)
        {
          if(!ff[i])p[++t]=i;
          for(int j=1;j<=t&&i*p[j]<=1000;j++){ff[i*p[j]]=true;if(i%p[j]==0 )break; }
        }
    }
    void dp()
    {
        f[0][0]=1;
        for(int i=1;i<=t;i++)
        {
          for(int j=0;j<=n;j++)f[i][j]=f[i-1][j];
          for(int j=p[i];j<=n;j*=p[i])
            for(int k=0;k<=n-j;k++)
               f[i][k+j]+=f[i-1][k];
        }
    }
    int main()
    {
        cin>>n; 
        get();
        dp();
        for(int i=0;i<=n;i++)ans+=f[t][i];
        cout<<ans<<endl;
    }



  • 相关阅读:
    Emote木马分析
    CentOS7安装部署MongoDB
    CentOS7搭建FastDFS文件管理服务器
    CentOS7搭建FTP服务器
    20179301《网络攻防实践》第九周作业
    20179301《网络攻防实践》第七周作业
    20179301 段晓庆 《网络攻防》第六周总结
    20179301 《网络攻防技术》第四周总结
    20179301 段晓庆 《网络攻防》第三周总结
    2017-2018-2 20179301《网络攻防技术》第一周作业
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/6936200.html
Copyright © 2011-2022 走看看