HDU 5668:Circle 同余方程

Circle

 
 Accepts: 62
 
 Submissions: 478
 Time Limit: 2000/1000 MS (Java/Others)
 
 Memory Limit: 65536/65536 K (Java/Others)
问题描述
\ \ \ \    Fye对约瑟夫游戏十分着迷.

\ \ \ \    她找到了nn个同学,把他们围成一个圈,让他们做约瑟夫游戏,然后她得到了一个同学们出圈的编号序列.游戏是这样进行的:以同学11为起点,开始计数,计数到第kk个同学,该同学出圈.出圈的同学将不参与之后的计数.

\ \ \ \    如今Fye找到了你,她想让你告诉他满足已知出圈序列的最小的kk,如果你回答不上来,她就会很生气然后把你吊打一顿.
输入描述
\ \ \ \    第一行一个数T,为测试数据组数.

\ \ \ \    对每组测试数据,第一行一个数nn.

\ \ \ \    第二行nn个数,为同学的出圈序列(第ai个出圈的人,编号为i).

\ \ \ \    输入数据必须是一个11nn的合法排列.

\ \ \ \ 1\le T \le 10,2 \le N\le 20    1T10,2N20.
输出描述
\ \ \ \    对于每组测试数据,若存在合法的kk,输出一个正整数,为合法的最小kk,否则输出”Creation August is a SB!“.
输入样例
1
7
7 6 5 4 3 2 1
输出样例
420

代码:

#pragma warning(disable:4996)
#include <iostream>
#include <functional>
#include <algorithm>
#include <cstring>
#include <vector>
#include <string>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <deque>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
typedef long double ld;

#define INF 0x333f3f3f
#define repp(i, n, m) for (int i = n; i <= m; i++)
#define rep(i, n, m) for (int i = n; i < m; i++)
#define sa(n) scanf("%d", &(n))

const ll mod = 1e9 + 7;
const int maxn = 2e5 + 5;
const double PI = acos(-1.0);


ll n, yue;
ll mi[30], ri[30];
ll aa[30], bb[30], dd[30];

void ex_gcd(ll a, ll b, ll &xx, ll &yy)
{
    if (b == 0)
    {
        xx = 1;
        yy = 0;
        yue = a;
    }
    else
    {
        ex_gcd(b, a%b, xx, yy);

        ll t = xx;
        xx = yy;
        yy = t - (a / b)*yy;
    }
}

void solve()
{
    ll i, j, k;
    ll cur_m = mi[1], cur_r = ri[1];
    ll f = 0;
    repp(i, 2, n)
    {
        ll xx, yy;
        ex_gcd(cur_m, mi[i], xx, yy);
        ll c = ri[i] - cur_r;
        if (c % yue != 0)
        {
            puts("Creation August is a SB!");
            return;
        }
        else
        {
            xx = ((xx* (c / yue)) % (mi[i] / yue) + (mi[i] / yue)) % (mi[i] / yue);
            cur_r = xx*cur_m + cur_r;
            cur_m = mi[i] / yue*cur_m;
        }
    }    
    printf("%lld\n", cur_r > 0 ? cur_r : cur_m);
}

void input()
{
    ll i, j, k;
    ll x, y;
    scanf("%lld", &n);

    repp(i, 1, n)
    {
        aa[i] = i;
        scanf("%lld", &k);
        bb[k] = i;
    }
    memset(dd, 0, sizeof(dd));
    for (y = 1, i = n; i >= 1; i--)
    {
        x = bb[n - i + 1];// bb[i]=k表示第i轮淘汰的是k
        //cout << i << " " << ((aa[x] - aa[y] + 1) % i + i) % i << endl;
        mi[n - i + 1] = i, ri[n - i + 1] = ((aa[x] - aa[y] + 1) % i + i) % i;
        //memset(aa, 0, sizeof(aa));
        for (dd[x] = 1, k = 0, j = 1; j <= n; j++)
        {
            if (!dd[j])
            {
                aa[j] = ++k;
            }
        }
        y = x;
    }
}

int main()
{
#ifndef ONLINE_JUDGE  
    freopen("i.txt", "r", stdin);
    freopen("o.txt", "w", stdout);
#endif

    int t;
    sa(t);
    while (t--)
    {
        input();
        solve();
    }
    
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值