zoukankan      html  css  js  c++  java
  • HDU 4259 Double Dealing 【离散数学】

    Problem Description
    Take a deck of n unique cards. Deal the entire deck out to k players in the usual way: the top card to player 1, the next to player 2, the kth to player k, the k+1st to player 1, and so on. Then pick up the cards – place player 1′s cards on top, then player 2, and so on, so that player k’s cards are on the bottom. Each player’s cards are in reverse order – the last card that they were dealt is on the top, and the first on the bottom.
    How many times, including the first, must this process be repeated before the deck is back in its original order?
     
    Input
    There will be multiple test cases in the input. Each case will consist of a single line with two integers, n and k (1≤n≤800, 1≤k≤800). The input will end with a line with two 0s.
     
    Output
    For each test case in the input, print a single integer, indicating the number of deals required to return the deck to its original order. Output each integer on its own line, with no extra spaces, and no blank lines between answers. All possible inputs yield answers which will fit in a signed 64-bit integer.
     
    Sample Input
    1 3 10 3 52 4 0 0
     
    Sample Output
    1 4 13
     

    思路:以10 3 为例:题意很好理解,
    1》通过一次变换,数值变化情况是
    1 2 3 4 5 6 7 8 9 10
    10 7 4 1 8 5 2 9 6 3
    通过一次变化,下标变化情况是
    1 2 3 4 5 6 7 8 9 10
    4 7 10 3 6 9 2 5 8 1
    2》由此可以看出来:位置的变化有如下规律:
    1->4->3->10->1;
    2->7->2;
    5->6->9->8->5;
    可以知道这一串的变化周期是一样的,想变化到以前的位置次数也是相同的;
    对于不同串的变换周期,要想最少nn次变化回来,那么要满足nn是他们的最小公倍数;
    3》对于求下标和容易知道最后一个数n在的第几列,可以依次把该列的都求出来
    那么根据这一列找到他右边的这里列最后的值即n+1-3,那么可以将此列的值全部求出来;
    4》这是离散数学的知识点轮换;
    1->4->3->10->1; 这称为一个轮换;
    (1->4->3->10->1)*(2->7->2)*(5->6->9->8->5)
    也就是3个轮换,每一个轮换中的元素无论执行多少次相同的置换都不会和其他轮换相交
    所以结果就是 lcm(4,2,3)=4

    代码如下:

    #include<stdio.h>
    #include<string.h>
    int a[1000], vis[1000];
    long long gcd(long long a, long long b) 
    { 
        return a ? gcd(b%a, a) : b; 
    }
    int main()
    {
        int i, j, n, k, t;
        while(scanf("%d%d", &n, &k)!=EOF)
        {
             if(n==0&&k==0)
                 break;
            t=0; 
            for(i=0; i<k&&i<n; i++)
                for(j=(n-i-1)/k*k+i; j>=0; j-=k)
                    a[t++]=j;
             memset(vis, 0, sizeof(vis));
             long long ans, lcmnum=1; 
            for(i=0; i<n; i++)
            {
                int x=i;
                ans=0; 
                while(!vis[x])
                {
                    ans++;
                    vis[x]=1; 
                    x=a[x];
                }
                if(ans) 
                    lcmnum=lcmnum/gcd(lcmnum, ans)*ans;
            }
            printf("%I64d\n", lcmnum);
        }
    }
  • 相关阅读:
    剑指Offer面试题:26.字符串的排列
    剑指Offer面试题:25.二叉搜索树与双向链表
    使用VS2013分析DMP文件
    目的 存在 问题 价值
    thinking models--基于事实和全方位思考
    目的-哲学解释
    亚里士多德.四因说
    存在与目的 人类与上帝
    我用过的数据库 sqlite realm mysql coredata
    swift Existential Container witness table
  • 原文地址:https://www.cnblogs.com/Hilda/p/2656864.html
Copyright © 2011-2022 走看看