[noi2002]荒岛野人 拓展欧几里得

克里特岛以野人群居而著称。岛上有排列成环行的M个山洞。这些山洞顺时针编号为1,2,…,M。岛上住着N个野人,一开始依次住在山洞C1,C2,…,CN中,以后每年,第i个野人会沿顺时针向前走Pi个洞住下来。每个野人i有一个寿命值Li,即生存的年数。下面四幅图描述了一个有6个山洞,住有三个野人的岛上前四年的情况。三个野人初始的洞穴编号依次为1,2,3;每年要走过的洞穴数依次为3,7,2;寿命值依次为4,3,1。

奇怪的是,虽然野人有很多,但没有任何两个野人在有生之年处在同一个山洞中,使得小岛一直保持和平与宁静,这让科学家们很是惊奇。他们想知道,至少有多少个山洞,才能维持岛上的和平呢?

枚举最小年份,然后判断此年份是否可行;

如何判断可行,只要两个野人有生之年都不会在一个洞里住,那么就可行;

枚举i,j野人,得ci-cj=(pj-pi)*x+ky      x表示会相遇的年份;

若无解,说明不会碰到;

否则用ex_gcd求出一个解,然后根据这个解求出x的最小正整数解,与min(l[i],l[j])比较一下,即可判断;

我犯的主要错误是,算出一个x后,x=x*(c[i]-c[j])/d,x=(x%k+k)%k,这里的k应换成k/d,这是由于x+k*t固然是它的解集,但是由于k和p[j]-p[i]之间还有一些公因数,所以漏掉了一些情况,所以计算之前先将k/d,这样就不会再wa了;

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string>
 5 #include<cstdlib>
 6 #include<ctime>
 7 #include<vector>
 8 #include<algorithm>
 9 #include<queue>
10 #include<map>
11 using namespace std;
12 #define LL long long
13 const int maxn=20;
14 void gcd(int a,int b,int &d,int &x,int &y){
15     if(b==0){d=a;x=1;y=0;return;}
16     gcd(b,a%b,d,x,y);
17     int t=x;
18     x=y;
19     y=t-a/b*x;
20 }
21 int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
22 int c[maxn],p[maxn],l[maxn],n,Left=0;
23 void init(){
24     cin>>n;
25     for(int i=1;i<=n;i++){cin>>c[i]>>p[i]>>l[i];Left=max(Left,c[i]);}
26     int x,y,d,kl;
27     for(int k=Left;k<=1000000;k++){
28         bool flag=0;
29         for(int i=1;i<=n;i++)
30             for(int j=i+1;j<=n;j++){
31                 if(flag)break;
32                 gcd(p[j]-p[i],k,d,x,y);
33                 if((c[i]-c[j])%d)continue;
34                 x=x*(c[i]-c[j])/d;
35                 kl=k/d;
36                 x=(x%kl+kl)%kl;
37                 if(x<=l[i]&&x<=l[j])flag=1;
38             }
39         if(!flag){printf("%d\n%d\n",k,clock());return;}
40     }
41 }
42 int main(){
43     freopen("1.in","r",stdin);
44     freopen("1.out","w",stdout);
45     init();
46     return 0;
47 }

其实我更想吐槽把10^6,弄成106的事情,即使一般有经验的人都不会被坑;

时间: 2024-08-07 21:16:46

[noi2002]荒岛野人 拓展欧几里得的相关文章

JZYZOJ1372 [noi2002]荒岛野人 扩展欧几里得

http://172.20.6.3/Problem_Show.asp?id=1372 想法其实很好想,但是我扩展欧几里得还是用得不熟练,几乎是硬套模板,大概因为今天一个下午状态都不大好.扩展欧几里得算法计算的是 : ab互质时ax+by=1或ab不互质时ax+by=gcd(a,b)(废话)的一个整数解,可以据此推导一个方程是否有解.然后我理解这个基本概念理解了一个下午,非常智障了.这道题也是模板,两两对比即可. 代码 1 #include<iostream> 2 #include<cst

cogs333 荒岛野人 扩展欧几里得

填坑--链接:http://cogs.pro/cogs/problem/problem.php?pid=333 题意:给出环上一堆移动的点,问环至少要有多长所有点才能都不被追上. 很久之前打的这道题--然而当时并不知道原理--今天重打时才意识到原理,于是来口胡一发-- 我们可以将野人之间追到看做$C[i]+x*P[i]=C[j]+x*P[j](mod m)$的一组正整数解中的$x$.如果追到,这个方程一定就是在这些野人有生之年内有整数解的.上面这个东西显然可以扩欧来解决,于是我们就可以直接枚举每

【lydsy1407】拓展欧几里得求解不定方程+同余方程

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1407 题意: 有n个野人,野人各自住在第c[i]个山洞中(山洞成环状),每年向前走p[i]个山洞,到这个山洞住下来. 每个野人的寿命为l[i],问至少需要多少个山洞,才能让野人在有生之年永远不住在同一个山洞. 题解: 原本不会拓展欧几里得和同余方程,在这里尽量详细地写一下由这题学到的东西. 我原本是从网上看各类题解然后打的,因为不理解和某些题解上的错误,导致调了很久. 下面写我的题解,如

bzoj4517: [Sdoi2016]排列计数--数学+拓展欧几里得

这道题是数学题,由题目可知,m个稳定数的取法是Cnm 然后剩下n-m本书,由于编号为i的书不能放在i位置,因此其方法数应由错排公式决定,即D(n-m) 错排公式:D[i]=(i-1)*(D[i-1]+D[i-2]); 所以根据乘法原理,答案就是Cnm * D(n-m) 接下来就是怎么求组合数的问题了 由于n≤1000000,因此只能用O(n)的算法求组合,这里用乘法逆元(inv[])来辅助求组合数 即 Cnm = n! / ((n-m)! * m!) = fac[n]*inv[n-m]*inv[

数论之拓展欧几里得求解不定方程和同余方程组(一)

今天接到scy的压缩包,开始做数论专题.那今天就总结一下拓展欧几里得求解不定方程和同余方程组. 首先我们复习一下欧几里得算法: 1 int gcd(int a,int b){ 2 if(b==0) return a; 3 return gcd(b,a%b);4 } 拓展欧几里得算法: 推导过程: 给出A和B,求它们的最大公约数,并且求出x和y,满足Ax+By=gcd(A,B). 当A=0时,x=0,y=1; 当A>0时, 因为exgcd(A,B,x,y)表示Ax+By=gcd(A,B) 而且ex

uva 10413 - Crazy Savages(拓展欧几里得)

题目链接:uva 10413 - Crazy Savages 题目大意:一座山有m个山洞,形成一个圈,现在有n个部落的人,每个部落一开始住在ci山洞,第2天会向后面移动pi个位置,一共会在这座山住li天.现在如果两个部落在同一个山洞相遇,则会发生战争,问说m最小时多少的时候,保证不会发生争斗. 解题思路:因为每个部落都有自己的存在时间,所以枚举m,然后枚举两个部落,判断他们有没有可能相遇. 假设在第k天: ci+k?pi=a?m???(1) cj+k?pj=b?m???(2) 由(2)-(1)得

uva 10548 - Find the Right Changes(拓展欧几里得)

题目链接:uva 10548 - Find the Right Changes 题目大意:给定A,B,C,求x,y,使得xA+yB=C,求有多少种解. 解题思路:拓展欧几里得,保证x,y均大于等于0,确定通解中t的取值. #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; typedef long long ll; co

POJ 1061 青蛙的约会(拓展欧几里得)

青蛙的约会 Time Limit: 1000MS   Memory Limit: 10000KB   64bit IO Format: %I64d & %I64u Submit Status Description 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置.不过青蛙们都是很乐观的,它们觉得只要一直朝着某个方向跳

poj2891 拓展欧几里得

1 //Accepted 164 KB 16 ms 2 //拓展欧几里得 3 //m=a1*x+b1 --(1) 4 //m=a2*(-y)+b2 --(2) 5 //->a1*x+a2*y=b2-b1 6 //由欧几里得算法可得上式的解 7 //由a*x+b*y=gcd(a,b) 8 //可得a(x+b)+b(y-a)=gcd(a,b) 9 //所以最小正整数解x=(x%b+b)%b; 10 //现考虑由(1)(2)两式得到的解m 11 //有x=m mod (a1*a2/gcd(a1,a2)