原 A-B数对(加强版)参见P1102c++
克里特岛以野人群居而著称。岛上有排列成环行的M个山洞。这些山洞顺时针编号为1,2,…,M。岛上住着N个野人,一开始依次住在山洞C1,C2,…,CN中,之后每一年,第i个野人会沿顺时针向前走Pi个洞住下来。spa
每一个野人i有一个寿命值Li,即生存的年数。code
下面四幅图描述了一个有6个山洞,住有三个野人的岛上前四年的状况。三个野人初始的洞穴编号依次为1,2,3;每一年要走过的洞穴数依次为3,7,2;寿命值依次为4,3,1。blog
奇怪的是,虽然野人有不少,但没有任何两个野人在有生之年处在同一个山洞中,使得小岛一直保持和平与宁静,这让科学家们非常惊奇。他们想知道,至少有多少个山洞,才能维持岛上的和平呢?it
第1行为一个整数N(1<=N<=15),即野人的数目。class
第2行到第N+1每行为三个整数Ci, Pi, Li (1<=Ci,Pi<=100, 0<=Li<=106 ),表示每一个野人所住的初始洞穴编号,每一年走过的洞穴数及寿命值。循环
仅包含一个数M,即最少可能的山洞数。输入数据保证有解,且M不大于10^6。gc
3 1 3 4 2 7 3 3 2 1
6
首先,对于第i个野人和第j个野人,咱们都但愿Ci+k*Pi≡Cj+k*Pj(mod ans)的k>他们两个寿命最短的一个,由于就算遇到了,也死了.........im
而后就有k*(Pi-Pj)+m*ans=Cj-Ci,就是裸的exgcd了................数据
1 #include<bits/stdc++.h> 2 using namespace std; 3 int c[101],p[101],l[101]; 4 int x,y; 5 int exgcd(int a,int b) 6 { 7 if(b==0) 8 { 9 x=1; 10 y=0; 11 return a; 12 } 13 int g=exgcd(b,a%b); 14 int z=x; 15 x=y; 16 y=z-(a/b)*y; 17 return g; 18 } 19 int main() 20 { 21 int n,maxc=0; 22 scanf("%d",&n); 23 for(int i=1;i<=n;i++) 24 { 25 scanf("%d%d%d",&c[i],&p[i],&l[i]); 26 maxc=max(maxc,c[i]);//确定从最大的编号开始枚举 27 } 28 for(int ans=maxc;;ans++)//枚举山洞的数量 29 { 30 bool flag=0; 31 for(int i=1;i<=n;i++) 32 { 33 for(int j=i+1;j<=n;j++)//双层循环,每两个野人一个同余方程 34 { 35 int k=p[i]-p[j]; 36 k=(k%ans+ans)%ans; 37 int g=exgcd(k,ans);//最大公约数 38 if((c[j]-c[i])%g)//若是这个解不合法 39 continue;//说明永远也碰不着 40 x*=((c[j]-c[i])/g);//求要追上的年数 41 int mod=ans/g; 42 x=(x%mod+mod)%mod; 43 if(x<=min(l[i],l[j]))//若是追上了 44 { 45 flag=1;//洞穴数量不合法标记退出 46 break; 47 } 48 } 49 if(flag)break; 50 } 51 if(flag)continue; 52 printf("%d",ans);//合法了就输出 53 return 0; 54 } 55 }