码迷,mamicode.com
首页 > 其他好文 > 详细

HDU5668 Circle 非互质中国剩余定理

时间:2016-04-18 23:52:32      阅读:299      评论:0      收藏:0      [点我收藏+]

标签:

分析:考虑对给定的出圈序列进行一次模拟,对于出圈的人我们显然可以由位置,编号等关系得到一个同余方程

一圈做下来我们就得到了n个同余方程 对每个方程用扩展欧几里得求解,最后找到最小可行解就是答案.

当然不要忘了判无解的情况. 有非常多选手似乎都是一眼标算然后写挂了,对此表示很遗憾,但是此题确实是比较容易写挂的...

 

注:中国剩余定理 解模线性方程组的时候

      有两种情况 1:一种是模数是两辆互质的,这样的题可以用LRJ白书上的模板,俗称CRT1

                        2:模数存在不互质的,这样的需要用合并方程的做法,俗称CRT2

CRT2可以在这位神犇的博客里找到(我就是看的这个,表示涨姿势)http://972169909-qq-com.iteye.com/blog/1266328

CRT1自行参照LRJ白书

 

AC代码:

技术分享
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
using namespace std;
typedef long long LL;
const int N=21;
int n,c[N];
bool vis[N];
LL a[N],m[N];
LL exgcd (LL a, LL b, LL &x, LL &y)
{
    if (b == 0)
    {
        x = 1, y = 0;
        return a;
    }
    LL d=exgcd(b,a%b,y,x);
    y-=a/b*x;
    return d;
}
LL CRT2 (LL a[], LL m[], int num)
{
    bool flag = false;
    LL n1 = m[1], n2, b1 = a[1], b2, bb, d, t, k, x, y;
    for (int i = 2; i <= num; i++)
    {
        n2 = m[i], b2 = a[i];
        bb = b2 - b1;
        d = exgcd (n1, n2, x, y);
        if (bb % d)
        {
            flag = true;
            break;
        }
        k = bb / d * x;
        t = n2 / d;
        if (t < 0) t = -t;
        k = (k % t + t) % t;
        b1 = b1 + n1*k;
        n1 = n1 / d * n2;
    }
    if (flag)
        return -1;
    if (b1 == 0)
        b1 = n1;
    return b1;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1; i<=n; ++i)
        {
            int x;
            scanf("%d",&x);
            c[x]=i;
        }
        memset(vis,0,sizeof(vis));
        int now=1;
        for(int i=1; i<=n; ++i)
        {
            int cnt=0;
            for(int j=now; j<=n+1; ++j)
            {
                if(j==n+1)j=1;
                if(vis[j])continue;
                ++cnt;
                if(j==c[i])break;
            }
            m[i]=(n-i+1);
            a[i]=cnt%m[i];
            vis[c[i]]=1;
             if(i==n)break;
            for(int j=c[i]; j<=n+1; ++j)
            {
                if(j==n+1)j=1;
                if(vis[j])continue;
                now=j;
                break;
            }
        }
        LL ans=CRT2(a,m,n);
        if(ans==-1)printf("Creation August is a SB!\n");
        else printf("%I64d\n",ans);
    }
    return 0;
}
View Code

 

 

HDU5668 Circle 非互质中国剩余定理

标签:

原文地址:http://www.cnblogs.com/shuguangzw/p/5406111.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!