• hdoj 4259 Double Dealing


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4259

    1. n张牌 (1,2,···,n) 按顺序发给k个人,再把牌收回,第1个人的放最上面,后面的依次放下面。继续发牌,收牌,问多少次后恢复原样。

    2. 以 n=10,k=3 为例,4次后牌的次序恢复原样,如下:

    第一次: 10  7  4   1   8   5   2   9   6   3
    第二次: 3   2  1   10  9   8   7   6   5   4
    第三次: 4   7  10  3   6   9   2   5   8   1
    第四次: 1   2  3    4   5   6   7   8   9   10

    3. 经过 1 次操作(发牌+收牌)后,下标变化情况如下:

    原次序:1  2  3    4  5  6  7  8  9  10
    操作后:4  7  10  3  6  9  2  5  8  1

    4. 显然,该操作为一个置换,且为:

    5. n 元数码上的任意置换 σ 都可唯一地表示成不相交的循环置换的乘积。

    6. lcm(x,y)=xy/gcd(x,y).

    7. lcm(x1,x2,···,xn)=lcm(lcm(x1,x2,···,xn-1),xn).

    8. 本题所求即为各循环置换的循环节的最小公倍数。以 n=10,k=3 为例,所求为 lcm(4,2,4)=4.

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 
     5 __int64 gcd(__int64 x,__int64 y){
     6     return y==0? x:gcd(y,x%y);
     7 }
     8 
     9 int main(){
    10     int n,k;
    11     while(scanf("%d%d",&n,&k),n||k){
    12         int t=n,i,j,f[805];
    13         for(i=k;i>=1;i--){  //f[i]:第i张牌经过一次变换后的位置
    14             for(j=i;j<=n;j+=k) f[t--]=j;
    15         }
    16         __int64 ans=1;
    17         bool flag[805]={0};
    18         for(i=1;i<=n;i++){
    19             if(flag[i]) continue;
    20             t=f[i];
    21             __int64 num=1;
    22             while(t!=i){
    23                 flag[t]=1;
    24                 t=f[t];
    25                 num++;
    26             }
    27             ans=ans/gcd(ans,num)*num;
    28         }
    29         printf("%I64d\n",ans);
    30     }
    31     return 0;
    32 }

  • 相关阅读:
    机器学习数学符号解释
    JVM Guide
    Mysql优化
    JAVA必会算法--冒泡排序
    HashMap-JDK源码阅读
    vue 下载文件
    CommonMethod
    log4net 写日志
    WebAPI 封装返回值
    二, .NET Core 微服务学习 ——集中式代理-Nginx
  • 原文地址:https://www.cnblogs.com/linqiuwei/p/3112484.html
Copyright © 2020-2023  润新知