HDU 5668 Circle

中国剩余定理。

可以手动模拟一下每一次开始的人的编号和结束的人的编号。

每次删掉一个人,对剩下的人重新编号。

这样一次模拟下来,可以得到n个方程

形如:(u[i]+k)%(n-i+1)=v[i]

化简一下就是:k%(n-i+1)=v[i]-u[i]%(n-i+1)

接下来就是求解最小的k,满足所有式子

中国剩余定理板子一套就AC了......

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;

typedef long long LL;
const int maxn = 30;
int n, T;
int s[maxn], flag[maxn], tmp[maxn];

int u[30], v[30];
LL a[maxn], b[maxn];

void ls()
{
    int cnt = 1;
    for (int i = 1; i <= n; i++)
    {
        if (flag[i] == 0)
            tmp[cnt++] = i;
    }
}

int Find(int a)
{
    for (int i = a; i <= n; i++)
        if (flag[i] == 0) return i;
    for (int i = 1; i <= a; i++)
        if (flag[i] == 0) return i;
}

int f2(int a)
{
    for (int i = 1;; i++)
        if (tmp[i] == a) return i;
}

void egcd(LL a, LL b, LL&d, LL&x, LL&y)
{
    if (!b) { d = a, x = 1, y = 0; }
    else
    {
        egcd(b, a%b, d, y, x);
        y -= x*(a / b);
    }
}

LL lmes() {
    LL M = a[1], R = b[1], x, y, d;
    for (int i = 2; i <= n; i++) {
        egcd(M, a[i], d, x, y);
        if ((b[i] - R) % d) return -1;
        x = (b[i] - R) / d*x % (a[i] / d);
        R += x*M;
        M = M / d*a[i];
        R %= M;
    }
    return (R + M) % M ? (R + M) % M : M;
}

void exgcd(LL a, LL b, LL &d, LL &x, LL &y)
{
    if (b == 0)
        d = a, x = 1, y = 0;
    else
    {
        exgcd(b, a%b, d, y, x);
        y -= x * (a / b);
    }
}

LL china(LL n, LL m[], LL a[])
{
    LL aa = a[0];
    LL mm = m[0];
    for (int i = 0; i<n; i++)
    {
        LL sub = (a[i] - aa);
        LL d, x, y;
        exgcd(mm, m[i], d, x, y);
        if (sub % d) return -1;

        LL new_m = m[i] / d;
        new_m = (sub / d*x%new_m + new_m) % new_m;
        aa = mm*new_m + aa;
        mm = mm*m[i] / d;
    }
    aa = (aa + mm) % mm;
    return aa ? aa : mm;
}

int main()
{
    scanf("%d", &T);
    while (T--)
    {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++)
        {
            int ai; scanf("%d", &ai);
            s[ai] = i;
        }
        memset(flag, 0, sizeof flag);

        u[1] = 0, v[1] = s[1];
        if (v[1] == n) v[1] = 0;

        flag[s[1]] = 1;

        for (int i = 2; i <= n; i++)
        {
            int st, en;
            ls();
            st = Find(s[i - 1]), st = f2(st), st = st - 1;
            if (st == -1) st = n - i;
            en = f2(s[i]), u[i] = st;
            v[i] = en; if (v[i] == n - i+1) v[i] = 0;
            flag[s[i]] = 1;
        }
        /*
        for (int i = 1; i <= n; i++)
            printf("%d %d\n", u[i], v[i]);
        */

        //接下来就是求解最小的k,满足所有式子
        //k%(n-i+1)=v[i]-u[i]%(n-i+1)

        for (int i = 1; i <= n; i++)
        {
            a[i] = (LL)(n - i + 1);
            b[i] = (LL)(v[i] - u[i] % (n - i + 1));
        }
        LL k = china(n, a + 1, b + 1);
        if (k == -1) printf("Creation August is a SB!\n");
        else printf("%lld\n", k);
    }
    return 0;
}
时间: 2024-10-29 01:14:48

HDU 5668 Circle的相关文章

hdu 5668 Circle 中国剩余定理

Circle Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Problem Description Satiya August is in charge of souls. He finds n souls,and lets them become a circle.He ordered them to play Joseph Games.The souls will cou

BestCoder Round #80 1004 hdu 5668 中国剩余定理(m不互质版)

链接:戳这里 Circle Time Limit: 2000/1000 MS (Java/Others)   Memory Limit: 65536/65536 K (Java/Others) 问题描述 \ \ \ \     Fye对约瑟夫游戏十分着迷. \ \ \ \     她找到了n个同学,把他们围成一个圈,让他们做约瑟夫游戏,然后她得到了一个同学们出圈的编号序列.游戏是这样进行的:以同学1为起点,开始计数,计数到第k个同学,该同学出圈.出圈的同学将不参与之后的计数. \ \ \ \  

HDU 5343 MZL&#39;s Circle Zhou

MZL's Circle Zhou Time Limit: 1000ms Memory Limit: 131072KB This problem will be judged on HDU. Original ID: 534364-bit integer IO format: %I64d      Java class name: Main MZL's Circle Zhou is good at solving some counting problems. One day, he comes

hdu 5343 MZL&#39;s Circle Zhou SAM

MZL's Circle Zhou 题意:给定两个长度不超过a,b(1 <= |a|,|b| <= 90000),x为a的连续子串,b为y的连续子串(x和y均可以是空串):问x+y形成的不同串的个数? 误区:开始一门心思想着求出总的可形成的字符串个数,再减去a,b中相同的子串重叠的部分:想通过连续插入a+b得到的SAM并不能获得信息:因为x,y是任意的子串,连续插入导致一定是a的后缀和b的前缀 正解:直接在计算有不同子串时,就不去计算重复的 <=>对于一个可能出现x后缀和y前缀相同

【后缀自动机】HDU 5343 MZL&#39;s Circle Zhou

通道 题意:从A,B分别取出子串X,Y,求多少种不同的X+Y 思路: 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAX_N = 200007; typedef unsigned long long ll; struct SAM { int val[MAX_N], fa[MAX_N], c[26][MAX_N]; int tot,

HDU 4669 Mutiples on a circle(DP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4669 题意:给出一个长度为n的数字环A和数字m.问有多少子串(连续)使得这些子串的数字拼在一起是m的倍数? 思路:首先计算A[1]和A[n]不在一起的.这个简单,只要记录f[i][j]表示到第i个数字余数为j的个数即可,然后: 接着计算a[1]和a[n]在一起的情况. 我们首先预处理end[i]表示数字子串A[i,n]连在一起对m的余数.然后枚举i从[1,n-1],那么数字设数字串[1,i]的长度为

hdu 5343 MZL&#39;s Circle Zhou(后缀自动机)

题目链接:hdu 5343 MZL's Circle Zhou 题意: 给你两个串A,B,问从A,B中选子串x,y,问x+y可以组成多少个不同的串,x和y可以为空. 题解: 贴一个官方的题解 1 #include<bits/stdc++.h> 2 #define mst(a,b) memset(a,b,sizeof(a)) 3 #define F(i,a,b) for(int i=(a);i<=(b);++i) 4 using namespace std; 5 using ll=unsi

HDU - 4669 Mutiples on a circle

Problem Description Tom has a necklace with n jewels. There is a number on each jewel. Now Tom wants to select a wonderful chain from the necklace. A chain will be regarded wonderful if the wonderful value of the chain is a multiple of a key number K

HDU 3980 Paint Chain(博弈 SG)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3980 Problem Description Aekdycoin and abcdxyzk are playing a game. They get a circle chain with some beads. Initially none of the beads is painted. They take turns to paint the chain. In Each turn one p