zoukankan      html  css  js  c++  java
  • poj 2891 扩展欧几里得解一元线性同余方程组

    http://poj.org/problem?id=2891

    题意:

    选择K个不同的正整数a1,a2.....ak,对于某个整数m分别对ai求余对应整数ri,如果当选择a1,a2,....ak,那么m可由整数对组合(ai,ri)唯一确定。

    现在已知a1,a2,...ak以及所有的整数对(ai,ri)求最小的非负整数m的值。

    设 a,b为整数,且a(!Ξ)0(mod)m,则称同余方程 ax Ξ b(mod)m为一次同余方程

    一次同余方程的求解步骤

    1:求gcd(a,m)

    2:令d = gcd(a,m) 如果d不能整除b则无解,否则转3

    3:根据ex_gcd 求得一个解x0;

    用扩展欧几里得求解的具体做法如下:

    (1):用ex_gcd求得满足 ax' + my' = d 的x'和y'。具体方法是将 ax'+my' = d 变形可以得到 ax' = d - my';

    对变形后的式子两边同时取模m得 ax'Ξd(mod)m,至此可见x'是同余方程的解

    (2):根据x'求x0。具体方法是:由于d能整除b 设 p = b/d,则根据同余式的性质得到:a(px')≡dp(mod)m即:a(px')≡b(mod)m.因此x0 = px' = b/d*x'(mod)m.

    4:根据求得的x0可以得到其他d-1个解为 xi = (x0 + i*m/d)(mod)m, i = 1,2,...d-1.

    然后根据上面的方法去解上面的题。代码是求得方程组小于m的非负整数解。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <stack>
     5 #include <queue>
     6 #include <map>
     7 #include <algorithm>
     8 #include <vector>
     9 
    10 using namespace std;
    11 
    12 const int maxn = 1000005;
    13 
    14 typedef long long LL;
    15 
    16 LL ex_gcd(LL a,LL b,LL &x,LL &y)
    17 {
    18    if(b == 0){
    19         x = 1;
    20         y = 0;
    21         return a;
    22    }
    23    LL r = ex_gcd(b,a%b,x,y);
    24    LL t = x;
    25       x = y;
    26       y = t - a/b*y;
    27       return r;
    28 }
    29 int main()
    30 {
    31     LL i,n,a1,r1,a2,r2,ans,a,b,c,d,x0,y0;
    32     while(scanf("%lld",&n)!=EOF){
    33         bool flag = 1;
    34         scanf("%lld%lld",&a1,&r1);
    35         for( i=1;i<n;i++){
    36             scanf("%lld%lld",&a2,&r2);
    37             a = a1;
    38             b = a2;
    39             c = r2-r1;
    40             LL d = ex_gcd(a,b,x0,y0);
    41             if(c%d!=0){
    42                 flag = 0;
    43             }
    44             int t = b/d;
    45             x0 = (x0*(c/d)%t+t)%t;//保证x0为正
    46             r1 = a1*x0 + r1;
    47             a1 = a1*(a2/d);
    48 
    49 
    50         }
    51         if(!flag){
    52             puts("-1");
    53             continue;
    54         }
    55         printf("%lld
    ",r1);
    56     }
    57     return 0;
    58 }
    View Code
  • 相关阅读:
    【转】我该 不该学习VULKAN
    游戏开发内功秘籍记录
    VS 配置外部DLL的引用路径【可执行文件的环境路径】
    OpenGL3.x,4.x中使用FreeImage显示图片的BUG-黑色,或颜色分量顺序错乱
    C++风格与C风格文件读写效率测试-vs2015,vs2017
    【转】矩阵的几何解释
    android 线程间通信
    android 网络
    安卓 碎片 如何实现类似 活动 栈的 进栈 出栈
    安卓 内容提供者 观察者 解析器
  • 原文地址:https://www.cnblogs.com/lmlyzxiao/p/4931129.html
Copyright © 2011-2022 走看看