程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> POJ 2115 C Looooops 【線性模方程】

POJ 2115 C Looooops 【線性模方程】

編輯:關於C語言

題意:轉化成c * x = b - a mod (2 ^ k),解這個模線性方程的最小正整數解即可

Sample Input
3 3 2 16
3 7 2 16
7 3 2 16
3 4 2 16
0 0 0 0

Sample Output
0
2
32766
FOREVER

解方程:ax == b (mod n);【ax % n == b % n】
設線性模方程的一個解為x0
條件①:有d = gcd(a, n)
條件②:有d = ax1 + ny, 由擴展歐幾裡得(Egcd)得到x1的值
條件③:b % d == 0 (有解的條件)
則x0 = x1*(b/d);

證明:
因為:容易求得d = gcd (a, n), 則有d = ax1 + ny①(擴展歐幾裡得定理)
方程①2邊同時模n得:d % n == ax1 % n②
又因為:b % d == 0, 即b是d的倍數;
所以(b/d)必為整數;
所以由②得: b % n == d*(b/d) % n == ax1*(b/d) % n == ax % n
所以很容易可以看出x = x1*(b/d)是方程的一個整數解,得證

參考文獻:

C++代碼 
#include <iostream>  
#include <fstream>  
#include <algorithm>  
#include <string>  
#include <set>  
//#include <map>  
#include <queue>  
#include <utility>  
#include <iomanip>  
#include <stack>  
#include <list>  
#include <vector>  
#include <cstdio>  
#include <cstdlib>  
#include <cstring>  
#include <cmath>  
#include <ctime>  
#include <ctype.h>  
using namespace std;  
#define L long long  
 
L Egcd (L a, L b, L &x, L &y)    //擴展歐幾裡得  
{  
    L d, tp;  
    if (b == 0)  
    {  
        x = 1, y = 0;  
        return a;  
    }  
    d = Egcd (b, a%b, x, y);  
    tp = x;  
    x = y;  
    y = tp - (a/b)*y;  
    return d;  
}  
void MLE (L a, L b, L n)    //解模線性方程  
{  
    L x, y, d;  
    d = Egcd (a, n, x, y);  
    if (b % d == 0)  
    {  
        L x0 = (b / d * x) % n + n;  
        cout << x0 % (n/d) << endl;  
//對於無數個解形成的一群余數:周期個數是d,周期長度是n/d,也就是最小正整數解在n/d裡,這個聽老師說過,但是忘了為什麼,涉及到群的概念……  
    }  
    else puts ("FOREVER");    //無解  
}  
int main()  
{  
    L a, b, c;  
    int k;  
    while (cin >> a >> b >> c >> k)  
    {  
        if (!a && !b && !c && !k)  
            break;  
        MLE (c, b - a, 1LL << k);  
    }  
    return 0;  

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved