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

bzoj 1407: [Noi2002]Savage【扩展欧几里得+中国剩余定理】

时间:2018-01-28 12:42:08      阅读:126      评论:0      收藏:0      [点我收藏+]

标签:class   扩展   cst   扩展欧几里得   turn   bre   blog   pac   编号   

首先答案不会很大,所以枚举答案m,于是把问题转为了判定;
关于如何判定:
首先题目中虽然没说但是数据是按照初始洞穴编号排的序,所以并不用自己重新再排
假设当前答案为m,相遇时间为x,野人i和j,那么可以列出同余式;
\[ x(p[i]-p[j])\equiv c[j]-c[i](mod\ m) \]
\[ x(p[i]-p[j])+ym=c[j]-c[i] \]
于是可解exgcd。由于并不是互质的,所以最后的算天数需要m/d

#include<cstdio>
using namespace std;
const int N=20;
int n,mx,a[N],b[N],c[N],d,x,y;
void exgcd(int a,int b,int &d,int &x,int &y)
{
    if(!b)
    {
        d=a,x=1,y=0;
        return;
    }
    exgcd(b,a%b,d,y,x);
    y-=a/b*x;//!!
}
bool ok(int m)
{
    for(int i=1;i<n;i++)
        for(int j=i+1;j<=n;j++)
        {
            int aa=((a[j]-a[i])%m+m)%m,bb=((b[i]-b[j])%m+m)%m;
            exgcd(bb,m,d,x,y);
            if(aa%d)
                continue;
            aa/=d;
            int mm=m/d,k=(aa*x%mm+mm)%mm;
            if(k<=c[i]&&k<=c[j])
                return 0;
        }
    return 1;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d%d",&a[i],&b[i],&c[i]);
        mx=max(a[i],mx);
        a[i]--;
    }
    for(int i=mx;;i++)
        if(ok(i))
        {
            printf("%d\n",i);
            break;
        }
    return 0;
}

bzoj 1407: [Noi2002]Savage【扩展欧几里得+中国剩余定理】

标签:class   扩展   cst   扩展欧几里得   turn   bre   blog   pac   编号   

原文地址:https://www.cnblogs.com/lokiii/p/8370660.html

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