zoukankan      html  css  js  c++  java
  • [BZOJ1025] [SCOI2009]游戏 解题报告

    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想知道,对于所有可能的对应关系,有多少种可能的排数。

      题意是让我们求回归到原序列的置换次数,也就是对于这个置换的每一个循环大小的最小公倍数

      如(123)(45)(6)

      对于第一个循环回归需要3x次(x代表任意自然数),第二个循环需要2x次,第三个循环需要x次

      显然对于这样的置换答案是6次

      有多少种可能的排数,也就是这个最小公倍数有多少种可能..?

      看起来比较奇怪的问题...

      我们用一个序列来表示最小公倍数

      2  3   5   7   11...997

      x1 x2  x3  x4  x5...x168

      最小公倍数就是2^x1*3^x2*5^x3...997^x168(说白了就是质因数分解>w<)

      对于每一个循环,它的大小质因数分解之后对于每个质因子的系数都<=上面的序列

      然后原问题就是满足题意的x1,x2..x168有多少种

      我们来考虑怎样才会不满足题意...

      首先x1,x2..x168再小也无所谓,因为就算全为0也是满足题意的,剩下的都可以用1来补全

      显然对于这些x最小的n就是2^x1+3^x2...+997^x168

      因为一旦2出现了x1次,说明一定有一个循环的个数中含有2^x1这个因子,我们令其中一个等于这个

      为了使n最小化,其它都不含2这个因子

      另外加法比乘法代价小这个显然...

      也就是说对于x序列的限制也就是2^x1+3^x2...997^x168<=n

      非常眼熟...非常简单的01背包...

      

     1 /**************************************************************
     2     Problem: 1025
     3     User: mjy0724
     4     Language: Pascal
     5     Result: Accepted
     6     Time:112 ms
     7     Memory:8236 kb
     8 ****************************************************************/
     9  
    10 program bzoj1025;
    11 const maxn=1010;
    12 var n,ans:int64;
    13     i,j,k:longint;
    14     p:array[-1..maxn]of int64;
    15     f:array[-1..maxn,-1..maxn]of int64;
    16     vis:array[-1..maxn]of boolean;
    17  
    18 procedure Euler;
    19 var i,j:longint;
    20 begin
    21     fillchar(vis,sizeof(vis),true);
    22     p[0]:=0;
    23     for i:=2 to n do
    24     begin
    25         if vis[i] then
    26         begin
    27             inc(p[0]);
    28             p[p[0]]:=i;
    29         end;
    30         for j:=1 to p[0] do
    31         begin
    32             if i*p[j]>n then break;
    33             vis[i*p[j]]:=false;
    34             if i mod p[j]=0 then break;
    35         end;
    36     end;
    37 end;
    38  
    39 begin
    40     readln(n);
    41     Euler;
    42     fillchar(f,sizeof(f),0);
    43     f[0,0]:=1;
    44     for i:=1 to p[0] do
    45         for j:=0 to n do
    46         begin
    47                         f[i][j]:=f[i-1][j];
    48             k:=p[i];
    49             while k<=j do
    50             begin
    51                 inc(f[i,j],f[i-1,j-k]);
    52                 k:=k*p[i];
    53             end;
    54         end;
    55     ans:=0;
    56     for i:=0 to n do inc(ans,f[p[0],i]);
    57     writeln(ans);
    58 end.
  • 相关阅读:
    说明因 Active Directory 冲突导致的 NTDS 复制警告 ID 1083 和 1061 以及 SAM 错误 ID 12294
    KB817701:可用于解决帐户锁定问题的 Service Pack 和修复程序
    log check
    AD account 锁定问题
    VS.2005 中比较有用的快捷键
    用户帐户意外锁定, 以及 Windows Server 2003 中记录事件 ID 12294
    xp 重新安装MDAC
    [学习收藏]业界三种架构优缺点比较
    [收藏学习]Linux内核虚拟机 学习KVM架构及其优点
    两个命令:hdparm和iozone参数解释
  • 原文地址:https://www.cnblogs.com/mjy0724/p/4421878.html
Copyright © 2011-2022 走看看