【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 }
复制代码

 

posted @   chty  阅读(220)  评论(0编辑  收藏  举报
编辑推荐:
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
阅读排行:
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 数据库服务器 SQL Server 版本升级公告
· C#/.NET/.NET Core技术前沿周刊 | 第 23 期(2025年1.20-1.26)
· 程序员常用高效实用工具推荐,办公效率提升利器!
点击右上角即可分享
微信分享提示