/*
*State: HDU4259    7796MS    3520K    1468 B    C++
*题目大意:
*        一副牌有n张,有k个人,轮流发牌,最后把每个人的牌按照小号在上,大号在下
*        的顺序叠放起来,求最少次数使牌恢复原样。
*解题思路:
*        发现每一张牌都有出现的周期,要恢复原状,只要求出每张牌出现的周期的最小
*        公倍数即可。
*解题感想;
*        用了STL里面的栈,结果20000ms都TLE了。可能是本题数据量太大,不过以后要慎用。
*        贡献了4~5个wa,查了好久好久,原来是这里虽然是_int64,但没有考虑到res[0] * 
*        res[1] / gcd(res[0], res[1]);这样会爆掉,所以一直wa.
*/
View Code
#include <iostream>
#include <cmath>
#include <stack>
using namespace std;

const int MAXN = 1805;
int a[2][MAXN], vst[MAXN], cnt;//cnt用来计算周期
int myS[MAXN][MAXN], top[MAXN];

void init()
{
    memset(vst, 0, sizeof(vst));
}

void dfs(int x)
{
    cnt++;
    vst[x] = 1;
    int nx = a[1][x];
    if(!vst[nx])
    {
        dfs(nx);
    }
}

__int64 gcd1(__int64 a, __int64 b)
{
    __int64 r = b, t;
    while(r)
    {
        t = r;
        r = a % r;
        a = t;
    }
    return a;
}

__int64 gcd2(__int64 a, __int64 b)
{
    return b == 0 ?  a : gcd2(b, a % b);
}

int main(void)
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif
    int n, k;
    while(scanf("%d %d", &n, &k), n || k)
    {
        init();
        for(int i = 0; i < n; i++)
        {
            int in = i % k;
            myS[in][top[in]++] = i;
        }
        int s = 0;
        for(int i = 0; i < n; i++)
            a[0][i] = i;

        for(int in = 0; in < k; in++)
        {
            while(top[in])
            {
                a[1][s++] = myS[in][--top[in]];
            }
        }

        int c = 0;
        __int64 res[MAXN];
        for(int i = 0; i < n; i++)
        {
            if(!vst[i])
            {
                cnt = 0;
                dfs(i);
                res[c++] = cnt;
            }
        }

        __int64 tmp;
        if(c >= 2)
        {
            //这里虽然是_int64,但没有考虑到res[0] * res[1] / gcd(res[0], res[1]);这样会爆掉,所以一直wa.
            tmp = res[0] / gcd2(res[0], res[1]) * res[1];
            for(int i = 2; i < c; i++)
                tmp = tmp / gcd2(tmp, res[i]) * res[i];
        }
        else if(c == 1)
            tmp = res[0];
        printf("%I64d\n", tmp);
    }
    return 0;
}
posted on 2012-08-26 19:11  cchun  阅读(285)  评论(0编辑  收藏  举报