【NOI2002】荒岛野人

【题解】

可以枚举m

那么任意两个野人之间有 c[i]+x*p[i]=c[j]+x*p[j] (mod m)  无解,或 x 的最小值<=min(l[i] , l[j])

化为丢番图方程:(p[i]-p[j])*x+m*y=c[j]-c[i]

用扩展欧几里得搞就行了。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<ctime>
 7 #include<algorithm>
 8 using namespace std;
 9 int n,mx,C[20],p[20],l[20];
10 inline int read()
11 {
12     int x=0,f=1;  char ch=getchar();
13     while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getchar();}
14     while(isdigit(ch))  {x=x*10+ch-'0';  ch=getchar();}
15     return x*f;
16 }
17 int gcd(int a,int b)  {return b==0?a:gcd(b,a%b);}
18 void exgcd(int a,int b,int &x,int &y)
19 {
20     if(b==0)  {x=1;  y=0;  return;}
21     exgcd(b,a%b,x,y);
22     int t=x;x=y;y=t-a/b*y;
23 }
24 bool check(int m)
25 {
26     for(int i=1;i<=n;i++)
27         for(int j=i+1;j<=n;j++)
28         {
29             int a=p[i]-p[j],b=m,c=C[j]-C[i],x,y;
30             int r=gcd(a,b);
31             if(c%r==0)
32             {
33                 a/=r;  b/=r;  c/=r;
34                 exgcd(a,b,x,y);
35                 b=abs(b);
36                 x=((x*c)%b+b)%b;
37                 while(!x)  x+=b;
38                 if(x<=min(l[i],l[j]))  return 0;
39             }
40         }
41     return 1;
42 }
43 int main()
44 {
45     //freopen("cin.in","r",stdin);
46     //freopen("cout.out","w",stdout);
47     n=read();
48     for(int i=1;i<=n;i++){C[i]=read();  p[i]=read();  l[i]=read();  mx=max(mx,C[i]);}
49     for(int i=mx;;i++)  if(check(i))  {printf("%d\n",i);  break;}
50     return 0;
51 }

 

转载于:https://www.cnblogs.com/chty/p/5957066.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值