• BZOJ1025


    1025: [SCOI2009]游戏

    Time Limit: 1 Sec  Memory Limit: 162 MB
    Submit: 2315  Solved: 1510
    [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个转换关系,这n个转换关系组成了m个环(m<=n) 然后每种转换的排的个数显然就是1+LCM(size[1],.....size[m]) ,令LCM(....)为ans  //size[i]是第i个环的大小。
    问题就变成了a1+a2+a3+a4...+am=n,求LCM(a1,a2,a3....am)的个数。
    又因为每个数字都能表示成p1^a1+p2^a2+p3^a3...这样的形式(p是素数)。
    则对任意p1^b1+p2^b2+p3^b3+p4^b4..+pm^bm<=n,都有一个ans=p1^b1*p2^b2*....*pm^bm;
    注意原来是等于n现在变成小于等于n,其实也比较好理解,因为有环大小为1的存在,将其不计入那么就出现小于n的情况了,而恰好不计入大小为1的环对答案没有什么影响。不能是大于n,否则所有环的大小加一起必定会大于n,与条件就不符合了。
     
    然后就是有一个让我费解的地方了:1.对于不同的n,只要得到这个n的方式不一样(由各种素数),那么ans的种类数cont就加一。2:并且不同的n之间不会出现重叠。//这个地方我暂时还不会证明。
    //http://hzwer.com/4397.html 代码来源
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    int n,tot,pri[1005];
    ll ans,f[1005][1005];
    bool mark[1005];
    void getpri(){
         for(int i=2;i<=1000;++i)
         {
             if(!mark[i]) pri[++tot]=i;
             for(int j=1;j<=tot&&i*pri[j]<=1000;++j) {
                mark[i*pri[j]]=1;
                if(i%pri[j]==0) break;
             }
         }
    }
    void solve(){
         f[0][0]=1;
         for(int i=1;i<=tot;++i){
            for(int j=0;j<=n;++j) f[i][j]=f[i-1][j];
            for(int j=pri[i];j<=n;j*=pri[i])
                for(int k=0;k<=n-j;++k)
                f[i][k+j]+=f[i-1][k];
         }
         for(int i=0;i<=n;++i) ans+=f[tot][i];
    }
    int main() {
       scanf("%d",&n);
       getpri();
       solve();
       printf("%lld
    ",ans);
    }
     
    另外抄一个打表大佬的打表
    http://blog.csdn.net/jiangshibiao/article/details/23040315
     
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=1005;
    int t[N],a[N],nn,n,ans;
    bool p[N*100],f[N];
    void count()
    {
      for (int i=1;i<=n;i++) t[i]=i;
      bool flag=true;int cnt=0;
      while (flag)
      {
        cnt++;
        flag=false;
        for (int i=1;i<=n;i++)
        {
          t[i]=a[t[i]];
          if (t[i]!=i) flag=true;
        }
      }
      if (!p[cnt]) ans++,p[cnt]=true;
    }
    void solve(int sta)
    {
      if (sta==n+1) count();
      for (int i=1;i<=n;i++)
        if (!f[i])
        {
          f[i]=true;
          a[sta]=i;
          solve(sta+1);
          f[i]=false;
        }
    }  
    int main()
    {
      scanf("%d",&nn);
      for (n=1;n<=nn;n++)
      {
      ans=0;
      memset(p,0,sizeof(p));
      memset(f,0,sizeof(f));
      solve(1);
      printf("%d ",ans);
      }
      return 0;
    }
  • 相关阅读:
    jQuery的选择器
    01-jQuery的介绍
    client、offset、scroll系列
    BOM
    定时器
    js中的面向对象
    javascript小练手
    DOM介绍
    关于DOM的事件操作
    伪数组 arguments
  • 原文地址:https://www.cnblogs.com/mfys/p/7003707.html
Copyright © 2020-2023  润新知