原 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 }