zoukankan      html  css  js  c++  java
  • 1025: [SCOI2009]游戏

    Time Limit: 1 Sec  Memory Limit: 162 MB
    Submit: 2727  Solved: 1794
    [Submit][Status][Discuss]

    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,1 <= N <= 1000

    Output

      包含一个整数,可能的排数。

    Sample Input

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

    Sample Output

    【输出样例一】
    3
    【输出样例二】
    16
     
    这其实更像一道数学题。。。
    以题目中N=6为例:
    1 2 3 4 5 6 对应的关系为 1->2 2->3 3->1 4->5 5->4 6->6
    可以划分为(1,2,3) (4,5) (6) 三个循环节,模拟计算几组数据后发现都可以划分为这样的循环节
    循环节的长度之和正好等于N,(即:3+2+1=6),而一个可能的排数等于LCM(循环节长度),即所有循环节长度的公倍数+1
    因此问题转化为:和为N的一串数,求它们的最小公倍数,而这一串数可以继续分解成更小的数(即这一串数不是固定的),并继续求最小公倍数,所有可能的最小公倍数的总数,即为方案数
    如:
    一串数    最小公倍数
    6        6
    5 1       5
    4 2       4
    4 1 1       4
    3 3       3
    。。。。。。
    最终可以发现可行的最小公倍数是:1,2,3,4,5,6,这六种,因此答案为6
    而怎么求这一串数又成了问题,这里可以反过来思考,一个可行的最小公倍数需要满足的条件。
    最小公倍数一定是一个合数,而一个合数可以分解为多个质数的积,那么最小公倍数的一个因数就是多个质数相乘后的积,并且需要满足所有因数的和小于等于N
    因此可以得到最小公倍数Z=a1^b1 × a2^b2 × a3^b3 × ...(a为质数),如6=3^1 × 2^1
    等于N我们都知道,至于为什么可以小于N,假设N=6为例,其中一种可行的最小公倍数,6=3^1×2^1,而3+2≤6。
    因为作为这一串数:
    一串数    最小公倍数
    3 2 1       6
    可以补1这种情况。
    接下来就要用到动态规划,设f[i][j],i表示前i个质数,j表示因数的和,表示前i个质数,因数和小于等于N的情况总数
     
     
     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 using namespace std;
     5 
     6 #define LL long long
     7 
     8 const int MAXN=10000;
     9 int cnt=0,prime[MAXN];
    10 int n;
    11 LL ans,f[200][1100];
    12 void Prime(int x)
    13 {
    14     bool mark[MAXN];
    15     for(int i=2;i<=x;i++)
    16     {
    17         if(!mark[i]) prime[++cnt]=i;
    18         for(int j=1;j<=cnt&&prime[j]*i<=x;j++)
    19         {
    20             mark[prime[j]*i]=1;
    21             if(i%prime[j]==0) break;
    22         }
    23     }
    24 }
    25 
    26 int main()
    27 {
    28     scanf("%d",&n);
    29     Prime(n);
    30     f[0][0]=1;
    31     for(int i=1;i<=cnt;i++)
    32         for(int j=0;j<=n;j++)
    33         {
    34             f[i][j]+=f[i-1][j];
    35             for(int k=prime[i];k<=j;k*=prime[i])
    36                 f[i][j]+=f[i-1][j-k];
    37         }
    38     for(int i=0;i<=n;i++)
    39         ans+=f[cnt][i];
    40     cout<<ans<<endl;
    41     return 0;
    42 }
  • 相关阅读:
    std thread
    windows更新包发布地址
    How to set up logging level for Spark application in IntelliJ IDEA?
    spark 错误 How to set heap size in spark within the Eclipse environment?
    hadoop 常用命令
    windows 安装hadoop 3.2.1
    windows JAVA_HOME 路径有空格,执行软连接
    day01MyBatisPlus条件构造器(04)
    day01MyBatisPlus的CRUD 接口(03)
    day01MyBatisPlus入门(02)
  • 原文地址:https://www.cnblogs.com/InWILL/p/9265698.html
Copyright © 2011-2022 走看看