zoukankan      html  css  js  c++  java
  • C Looooops(扩展欧几里得求模线性方程)

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

    题意:对于C的循环(for i = A; i != B; i+=C)问在k位存储系统内循环多少次结束;

       若循环有限次能结束输出次数,否则输出 FOREVER;

    解:设x为循环次数;

       (A+C*x)%2^k = B;  

      则 C*x+A = 2^k*y+B; 

      所以 C*x - 2^k*y = B-A; 类似于a*x+b*y = c (或 a*x = c(mod b))模线性方程的形式,所以可以根据扩展欧几里得算法解决

      

     1 #include<stdio.h>
     2 #include<string.h>
     3 
     4 long long exGcd(long long a,long long b,long long &x, long long &y)
     5 {
     6     if(b == 0)
     7     {
     8         x = 1;
     9         y = 0;
    10         return a;
    11     }
    12     long long d = exGcd(b,a%b,x,y);
    13     long long t = x;
    14     x = y;
    15     y = t-a/b*y;
    16     return d;
    17 }//a,b的最大公约数是d,且d = x*a+y*b表示;
    18 
    19 int main()
    20 {
    21     long long A,B,C,a,b,n;
    22     int k;
    23 
    24     while(~scanf("%lld %lld %lld %d",&A,&B,&C,&k))
    25     {
    26         if(A == 0 && B == 0 && C == 0 && k == 0)
    27             break;
    28         a = C;
    29         b = B-A;
    30         n = 1LL<<k;//因为n是long long,所以2^k要写成lLL<<k;
    31 
    32         long long x,y,d;
    33         d = exGcd(a,n,x,y);
    34         if(b%d != 0)
    35             printf("FOREVER
    ");
    36         else
    37         {
    38             x = (x*(b/d))%n;//方程a*x = b(mod n)的最小解(其实我也不清楚怎么的得到的x0,先记着呗);
    39             x = (x%(n/d)+n/d)%(n/d);//方程a*x = b(mod n)的最小整数解;
    40             printf("%lld
    ",x);
    41         }
    42     }
    43     return 0;
    44 
    45 }
    View Code

     

    推论1: 方程ax≡b(mod n)对于未知量x有解,当且仅当gcd(a,n) | b (b能被gcd(a,n)整除)。

    即:若gcd(a,n)|b ==> 有一个解x,使得ax≡b(mod n).   

    推论2:方程ax≡b(mod n)或者对模n有d个不同的解(有解当且仅当d | b),其中d=gcd(a,n),或者无解。   

    定理1:设d=gcd(a,n),假定对整数x'和y'满足d=ax'+ny'(比如用扩展Euclid算法求出的一组解)。如果d | b,则该方程对模n有d个不同的解,方程ax≡b(mod n)有一个解x0满足x0=x'*(b/d) mod n 通解为xi = x0 + i*(n / d)(d = 0, 1, 2, ..., d - 1)。特别的设e=x0+n,方程ax≡b(mod n)的最小整数解x1=e mod (n/d),最大整数解x2=x1+(d-1)*(n/d)。

    定理2:假设方程ax=b(mod n)有解,且x0是方程的任意一个解,则该方程对模n恰有d个不同的解(d=gcd(a,n)),分别为:xi=x0+i*(n/d) mod n 。

     

    类似地: 可以求ax + by = c的整数解(x, y)。==> ax ≡ c(mod b), d = gcd(a, b) | c 时有解。有一个解x0 = x’* (c / d) mod b,  y0 = (-a * x0 - c) / b; 通解xi = x0 + i * (b / d), yi = y0 - i * (a / d) (i = 0, 1, 2, ..., d - 1)。

    扩展欧几里得算法
    int exgcd(int a, int b, int& x, int& y)
    {
    if(b == 0)
    {
    x = 1;
    y = 0;
    return a;
    }
    int r = exgcd(b, a%b, x, y);
    int t = x;
    x = y;
    y = t - a/b* y;
    return r;
    }

     

  • 相关阅读:
    JavaScript知识回顾
    HTML和CSS相关知识回顾
    springmvc文件上传和下载
    jsp页面调试中的问题记录
    mybatis传参的几种方式
    ssm中调试遇到的坑
    idea新手日记
    Oracle安装
    mysql5安装
    Servlet 的原理----无脑笔记
  • 原文地址:https://www.cnblogs.com/LK1994/p/3365969.html
Copyright © 2011-2022 走看看