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))
12 //m是最小正整数解,m+a1*a2/gcd(a1,a2)也是(1)(2)的解
13 #include <cstdio>
14 #include <cstring>
15 #include <iostream>
16 using namespace std;
17 __int64 extend_gcd(__int64 a,__int64 b,__int64 &x,__int64 &y)
18 {
19     if (b==0)
20     {
21         x=1;
22         y=0;
23         return a;
24     }
25     __int64 r=extend_gcd(b,a%b,x,y);
26     __int64 t=x;
27     x=y;
28     y=t-a/b*y;
29     return r;
30 }
31 int main()
32 {
33     int n;
34     while (scanf("%d",&n)!=EOF)
35     {int flag=0;
36     __int64 a1,b1,a2,b2;
37     __int64 x,y,c,d;
38     scanf("%I64d%I64d",&a1,&b1);
39     for (int i=2;i<=n;i++)
40     {
41         scanf("%I64d%I64d",&a2,&b2);
42         if (flag) continue;
43         d=extend_gcd(a1,a2,x,y);
44         c=b2-b1;
45         if (c%d)
46         {
47             flag=1;
48         }
49         else
50         {
51             __int64 p=a2/d;
52             x=(c/d*x%p+p)%p;
53             b1=a1*x+b1;
54             a1=a1/d*a2;
55         }
56     }
57     if (flag) printf("-1\n");
58     else printf("%I64d\n",b1);
59     }
60     return 0;
61 }

时间: 2024-08-25 09:37:19

poj2891 拓展欧几里得的相关文章

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

今天接到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

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[

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 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置.不过青蛙们都是很乐观的,它们觉得只要一直朝着某个方向跳

uva 1426 - Discrete Square Roots(拓展欧几里得)

题目链接:uva 1426 - Discrete Square Roots 题目大意:给出X,N,R,求出所有满足的r,使得r2≡x%N,并且R是一个其中的解. 解题思路: R2?r2=k?N (R?r)(R+r)=k?N => aA=(R+r),bB=(R?r),A,B为N的因子 所以枚举A,B,就有r=R?aA=bB?R aA+bB=2?R 拓展欧几里得求解,将所有满足的解放入set中自动去重. #include <cstdio> #include <cstring> #

题解: poj 1061 nefu 84(拓展欧几里得)

POJ1061 Language:Default 青蛙的约会 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 105002 Accepted: 20595 Description 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置.不过青蛙们都是很乐观

HDU 1576 A/B(拓展欧几里得)

Problem Description 要求(A/B)%9973,但由于A很大,我们只给出n(n=A%9973)(我们给定的A必能被B整除,且gcd(B,9973) = 1). Input 数据的第一行是一个T,表示有T组数据. 每组数据有两个数n(0 <= n < 9973)和B(1 <= B <= 10^9). Output 对应每组数据输出(A/B)%9973. Sample Input 2 1000 53 87 123456789 Sample Output 7922 60

拓展欧几里得模板

数论拓展欧几里得,计算mx+ny=d的一组解(m.n为已知) int xx=x+n/d*i; int yy=y-m/d*i;//xx,yy分别为其它通解 void extend_gcd(int a,int b,int &x,int &y,int &d) { if(!b) { x=1; y=0; d=a; return; } extend_gcd(b,a%b,x,y,d); int t=x-a/b*y; x=y; y=t; }