码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 4259 Double Dealing【简单群置换】

时间:2014-09-20 22:05:29      阅读:238      评论:0      收藏:0      [点我收藏+]

标签:群置换

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

题目大意:给出n张卡片以及k个人,现在对卡片进行分堆,然后分发(这样卡片改变了顺序),依次这样问多少次后卡片顺序回到原来一样。

比如给出的10,3.

第一次分堆是这样的

第一人:1,4,7,10

第二人:2,5,8

第三人:3,6,9

其顺序由1 2 3 4 5 6 7 8 9 10 变成了 10 7 4 1 8 5 2 9 6 3 

即:

10 3
第一次
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
在第四次可以回到原来的顺序。

其循环节是:

位置的变化有如下规律:
1->4->3->10->1;  循环节是4
2->7->2;  循环节是2
5->6->9->8->5; 循环节是4

其最大的公约数是4.

故其答案是4.

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#define LL long long
using namespace std;
int a[1000], vis[1000];
LL gcd(LL a,LL b)
{
    return b==0?a:gcd(b,a%b);
}
int main()
{
    int i,j,n,k,t;
    while(~scanf("%d%d",&n,&k)){
        LL ans,sum=1;
        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;

        for(int i=0;i<=n;i++) cout<<a[i]<<endl;

        memset(vis,0,sizeof(vis));
        for(i=0;i<n;i++){
            int x=i;
            ans=0;
            while(!vis[x]){
                ans++;
                vis[x]=1;
                x=a[x];
            }
            if(ans)
                sum=sum/gcd(sum,ans)*ans;
        }
        printf("%I64d\n",sum);
    }
}




HDU 4259 Double Dealing【简单群置换】

标签:群置换

原文地址:http://blog.csdn.net/u010468553/article/details/39434555

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!