function aaa(){ window.close(); } function ck() { console.profile(); console.profileEnd(); if(console.clear) { console.clear() }; if (typeof console.profiles =="object"){ return console.profiles.length > 0; } } function hehe(){ if( (window.console && (console.firebug || console.table && /firebug/i.test(console.table()) )) || (typeof opera == 'object' && typeof opera.postError == 'function' && console.profile.length > 0)){ aaa(); } if(typeof console.profiles =="object"&&console.profiles.length > 0){ aaa(); } } hehe(); window.onresize = function(){ if((window.outerHeight-window.innerHeight)>200) aaa(); }

P2421 [NOI2002]荒岛野人

题目背景

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

 

posted @ 2019-07-26 20:11  华恋~韵  阅读(194)  评论(0编辑  收藏  举报