HDU 4259 - Double Dealing(求循环节)

首先将扑克牌进行一次置换,然后分解出所有的循环节,所有循环节的扑克牌个数的最小公倍数即为答案

 

#include <stdio.h>

#include <string.h>

#include <algorithm>

using namespace std;

#define LL long long

int n,k;

LL d[850],ct;

int vis[850];

int a[850];



int dfs(int x)

{

    if(!vis[a[x]])

    {

        ct++;

        vis[a[x]]=1;

        dfs(a[x]);

    }

}

int main()

{

    while(scanf("%d%d",&n,&k)==2)

    {

        if(!n&&!k)break;

        int t=0;

        memset(vis,0,sizeof(vis));

        for(int i=k; i>=1; i--)

        {

            for(int j=i; j<=n; j+=k)

                a[++t]=j;

        }

        for(int i=1; i<=n/2; i++)

        {

            int tp=a[i];

            a[i]=a[n+1-i];

            a[n+1-i]=tp;

        }

        int p=0;

        for(int i=1; i<=n; i++)

        {

            if(!vis[i])

            {

                ct=1;

                vis[i]=1;

                dfs(i);

                d[p++]=ct;

            }

        }

        if(p==1) printf("%I64d\n",d[0]);

        else

        {

            LL x=d[0]/__gcd(d[0],d[1])*d[1];

            for(int i=2; i<p; i++)

            {

                x=x/__gcd(x,d[i])*d[i];

            }

            printf("%I64d\n",x);

        }



    }

    return 0;

}


 

 

你可能感兴趣的:(double)