题目背景
原 A-B数对(增强版)参见P1102
题目描述
克里特岛以野人群居而著称。岛上有排列成环行的M个山洞。这些山洞顺时针编号为1,2,…,M。岛上住着N个野人,一开始依次住在山洞C1,C2,…,CN中,以后每年,第i个野人会沿顺时针向前走Pi个洞住下来。
每个野人i有一个寿命值Li,即生存的年数。
下面四幅图描述了一个有6个山洞,住有三个野人的岛上前四年的情况。三个野人初始的洞穴编号依次为1,2,3;每年要走过的洞穴数依次为3,7,2;寿命值依次为4,3,1。
奇怪的是,虽然野人有很多,但没有任何两个野人在有生之年处在同一个山洞中,使得小岛一直保持和平与宁静,这让科学家们很是惊奇。他们想知道,至少有多少个山洞,才能维持岛上的和平呢?
输入格式
第1行为一个整数N(1<=N<=15),即野人的数目。
第2行到第N+1每行为三个整数Ci, Pi, Li (1<=Ci,Pi<=100, 0<=Li<=106 ),表示每个野人所住的初始洞穴编号,每年走过的洞穴数及寿命值。
输出格式
仅包含一个数M,即最少可能的山洞数。输入数据保证有解,且M不大于10^6。
输入输出样例
输入 #1
3 1 3 4 2 7 3 3 2 1
输出 #1
6
解题思路
首先,对于第i个野人和第j个野人,我们都希望Ci+k*Pi≡Cj+k*Pj(mod ans)的k>他们两个寿命最短的一个,因为就算遇到了,也死了.........
然后就有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 }