[bzoj1407][exgcd]Savage

109 篇文章 4 订阅
63 篇文章 0 订阅

Description

引用块内容

Input

第1行为一个整数N(1<=N<=15),即野人的数目。
第2行到第N+1每行为三个整数Ci, Pi, Li表示每个野人所住的初始洞穴编号,每年走过的洞穴数及寿命值。
(1<=Ci,Pi<=100, 0<=Li<=10^6 )

Output

仅包含一个数M,即最少可能的山洞数。输入数据保证有解,且M不大于10^6。

Sample Input

3
1 3 4
2 7 3
3 2 1

Sample Output

6

题解

复习了一把Exgcd,顺带填了之前的坑嘿嘿嘿
对于两个野人i,j,可以列出一个同余方程
c[i]+p[i]*x=c[j]+p[j]*x (mod m)
然后拆一下就变成了(p[i]-p[j])*x-m*y=c[j]-c[i]
exgcd求出x的最小解,判一下是不是小于min(l[i],l[j]),然后这就是check了
那么我们枚举m,在check里面枚举i,j,exgcd判断,由于n<=15所以就一通乱gay就好

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
/*
    c[i]+p[i]*x=c[j]+p[j]*x (mod m)
    (p[i]-p[j])*x-m*y=c[j]-c[i]
*/
LL exgcd(LL a,LL b,LL &x,LL &y)
{
    if(a==0)
    {
        x=0;y=1;
        return b;
    }
    else
    {
        LL tx,ty;
        LL d=exgcd(b%a,a,tx,ty);
        x=ty-(b/a)*tx;
        y=tx;
        return d;
    }
}
int n;
LL c[30],p[30],l[30];
bool check(int m)
{
    for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
            {
                LL a=p[i]-p[j],b=(LL)m,k=c[j]-c[i];
                LL x,y;
                LL d=exgcd(a,b,x,y);
                if(k%d)continue;
                x=x*(k/d);x=x%(b/d);
                if(x<0)x+=abs(b/d);
                if(x<=min(l[i],l[j]))return false;
            }
    return true;
}
int main()
{
    scanf("%d",&n);
    LL ans=n;
    for(int i=1;i<=n;i++){scanf("%lld%lld%lld",&c[i],&p[i],&l[i]);ans=max(ans,c[i]);}
    for(ans;ans<=1000000;ans++)if(check(ans)){printf("%lld\n",ans);return 0;}
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值