ACM学习历程—HDU5668 Circle(数论)

http://acm.hdu.edu.cn/showproblem.php?pid=5668

这题的话,假设每次报x个,那么可以模拟一遍,

假设第i个出局的是a[i],那么从第i-1个出局的人后,重新报数到他假设经过了p个人,

那么自然x = k(n-i)+p(0<= i < n)

即x = p (mod n-i)

然后显然可以得到n个这样的方程,于是就是中国剩余定理了。

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <string>
#define LL long long

using namespace std;

int n, s[25];
bool vis[25];
LL rest[25], mmod[25];

LL gcd(LL a, LL b)
{
    LL r;
    while (b != 0)
    {
        r = b;
        b = a%b;
        a = r;
    }
    return a;
}

LL lcm(LL a, LL b)
{
    return a/gcd(a, b)*b;
}

//EXGCD
//求解方程ax+by=d,即ax=d mod(b)
//扩展可求逆元
//O(logn)
void exgcd(LL a, LL b, LL &x, LL &y, LL &d)
{
    if (b == 0)
    {
        x = 1;
        y = 0;
        d = a;
    }
    else
    {
        exgcd(b, a%b, y, x, d);
        y -= a/b*x;
    }
}

//中国剩余定理(非互质)
//其中a为除数数组,n为模数数组
LL inv(LL a, LL n)
{
    LL x, y, d;
    exgcd(a, n, x, y, d);
    if (d != 1)
        return -1;
    return (x%n + n) % n;
}

bool Merge(LL a1, LL n1, LL a2, LL n2, LL &aa, LL &nn)
{
    LL d = gcd(n1, n2);
    LL c = a2 - a1;
    if (c % d)
        return false;
    //(n1/d)*k1 = (c/d)(mod(n2/d))
    c /= d;
    n1 /= d;
    n2 /= d;
    //k1 = (c/d)*(n1/d)^(-1)(mod(n2/d))
    c *= inv(n1, n2);
    c %= n2;//k1
    c *= n1 * d;//a = n1*k1+a1
    c += a1;
    nn = n1*n2*d;
    aa = c;
    return true;
}

LL CRT(int len, LL *a, LL *n)
{
    LL a1 = a[0], n1 = n[0];
    LL a2, n2;
    for (int i = 1; i < len; i++)
    {
        LL aa, nn;
        a2 = a[i], n2 = n[i];
        if (!Merge(a1, n1, a2, n2, aa, nn))
            return -1;
        a1 = aa;
        n1 = nn;
    }
    return (a1%n1 + n1) % n1;
}

void work()
{
    LL ans, tmp = 1;
    memset(vis, false, sizeof(vis));
    int now = 0, step, t = 0;
    for (int i = 0; i < n; ++i)
    {
        step = 0;
        for (int j = t%n; j < n; j = (j+1)%n)
        {
            if (vis[j]) continue;
            step++;
            if (j == s[now])
            {
                now++;
                vis[j] = true;
                rest[i] = step%(n-i);
                mmod[i] = n-i;
                tmp = lcm(tmp, n-i);
                t = j;
                break;
            }
        }
    }
    ans = CRT(n, rest, mmod);
    if (ans == -1)
        printf("Creation August is a SB!\n");
    else
    {
        ans = (ans%tmp+tmp)%tmp;
        if (ans == 0) ans = tmp;
        cout << ans << endl;
    }
}

int main()
{
    //freopen("test.in", "r", stdin);
    int T, u;
    scanf("%d", &T);
    for (int times = 1; times <= T; ++times)
    {
        scanf("%d", &n);
        for (int i = 0; i < n; ++i)
        {
            scanf("%d", &u);
            s[u-1] = i;
        }
        work();
    }
    return 0;
}

时间: 2024-10-14 12:12:32

ACM学习历程—HDU5668 Circle(数论)的相关文章

ACM学习历程—HDU 4726 Kia&#39;s Calculation( 贪心&amp;&amp;计数排序)

DescriptionDoctor Ghee is teaching Kia how to calculate the sum of two integers. But Kia is so careless and alway forget to carry a number when the sum of two digits exceeds 9. For example, when she calculates 4567+5789, she will get 9246, and for 12

ACM学习历程—HDU 5023 A Corrupt Mayor&#39;s Performance Art(广州赛区网赛)(线段树)

Problem Description Corrupt governors always find ways to get dirty money. Paint something, then sell the worthless painting at a high price to someone who wants to bribe him/her on an auction, this seemed a safe way for mayor X to make money. Becaus

ACM学习历程—UESTC 1226 Huatuo&#39;s Medicine(数学)(2015CCPC L)

题目链接:http://acm.uestc.edu.cn/#/problem/show/1226 题目就是构造一个对称的串,除了中间的那个只有1个,其余的两边都是对称的两个,自然答案就是2*n-1. 代码: #include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <algorithm> #

ACM学习历程—HDU5585 Numbers(数论 || 大数)(BestCoder Round #64 (div.2) 1001)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5585 题目大意就是求大数是否能被2,3,5整除. 我直接上了Java大数,不过可以对末尾来判断2和5,对所有位的和来判断3. 代码就不粘了.

ACM学习历程—广东工业大学2016校赛决赛-网络赛F 我是好人4(数论)

题目链接:http://gdutcode.sinaapp.com/problem.php?cid=1031&pid=5 这个题目一看就是一道数论题,应该考虑使用容斥原理,这里对lcm进行容斥. 不过直接上去是T,考虑到序列中同时存在i和ki的话,其实只需要考虑i,所以先对序列中为倍数的对进行处理. 这里的容斥用了hqw的写法. 代码: #include <iostream> #include <cstdio> #include <cstdlib> #includ

ACM学习历程—HDU5637 Transform(数论 &amp;&amp; 最短路)

题目链接:http://codeforces.com/problemset/problem/590/A 题目大意是给两种操作,然后给你一个s,一个t,求s至少需要多少次操作到t. 考虑到第一种操作是将某一位取反,而第二种操作是抑或一个数. 显然第一种操作也是可以通过抑或一个数得到的.比如:第i位取反,相当于抑或(1<<i)这个数.于是就将n个数扩大到n+17就可以了,因为100000最多17位. 此外如果p^a^b^c...=q的话,那么a^b^c...=p^q.于是,只需要求出p^q至少需要

ACM学习历程—SNNUOJ1132 余数之和(数论)

Description F(n) = (n % 1) + (n % 2) + (n % 3) + ...... (n % n).其中%表示Mod,也就是余数.例如F(6) = 6 % 1 + 6 % 2 + 6 % 3 + 6 % 4 + 6 % 5 + 6 % 6 = 0 + 0 + 0 + 2 + 1 + 0 = 3.给出n,计算F(n). Input 输入1个数N(2 <= N <= 10^12). Output 输出F(n). Sample Input 6 Sample Output

ACM学习历程—HDU 3092 Least common multiple(数论 &amp;&amp; 动态规划 &amp;&amp; 大数)

hihoCoder挑战赛12 Description Partychen like to do mathematical problems. One day, when he was doing on a least common multiple(LCM) problem, he suddenly thought of a very interesting question: if given a number of S, and we divided S into some numbers

ACM学习历程—HDU 5446 Unknown Treasure(数论)(2015长春网赛1010题)

Problem Description On the way to the next secret treasure hiding place, the mathematician discovered a cave unknown to the map. The mathematician entered the cave because it is there. Somewhere deep in the cave, she found a treasure chest with a com