码迷,mamicode.com
首页 > 其他好文 > 详细

poj 2115 (解单变元模线性方程)

时间:2015-01-31 16:30:04      阅读:242      评论:0      收藏:0      [点我收藏+]

标签:algorithm   数论   

poj 2115 (解单变元模线性方程)

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


题意:
给出a,b,c,k,求x,使得(a+c*x)%(2^k)=b
限制:
0 <= a,b,c < 2^k; 1 <= k <= 32
思路:
拓展欧几里得单变元模线性方程
令 A=c;C=((b-a)%(2^k)+2^k)%(2^k);B=2^k
则这道题就化为Ax%n=B


对于Ax%B=C
-> Ax+By=C
-> d=Ext_gcd(A,B,x,y) //d其实为gcd(A,B)
-> if(C%d!=0) 无解 else 有解
-> x=(x*(C/d)%(B/d)+(B/d))%(B/d) ------1式//为最小自然数解(最小为0)


现在推导1式:
对Ax%B=C 即: Ax+By=C
d=gcd(A,B),则存在一个x1,y(可以由拓展欧几里得求出)使得 d=Ax1+By ---2式
由"2式"两边同时模B得:d%B=Ax1%B ---3式
又因为:C%d==0
所以(B/d)为整数
所以由"3式"得:C%B=(C/d)*d%B  =  (C/d)*Ax1%B=A(x1*C/d)%B
即:C%B=A(x1*C/d)%B
所以x=x1*(C/d)是一个整数解
又Ax%B=C -> (A/d)x%(B/d)=C/d -> 可以看出解集为x+k*(B/d) (k=整数)

所以最小整数解x0 = (x%(B/d)+(B/d))%(B/d) = (x1*(C/d)%(B/d)+(B/d))%(B/d)


 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/*poj 2115
  题意:
  给出a,b,c,k,求x,使得(a+c*x)%(2^k)=b
  限制:
  0 <= a,b,c < 2^k; 1 <= k <= 32
  思路:
  拓展欧几里得单变元模线性方程
  令 A=c;C=((b-a)%(2^k)+2^k)%(2^k);B=2^k
  则这道题就化为Ax%n=B

  对于Ax%B=C
  -> Ax+By=C
  -> d=Ext_gcd(A,B,x,y) //d其实为gcd(A,B)
  -> if(C%d!=0) 无解 else 有解
  -> x=(x*(C/d)%(B/d)+(B/d))%(B/d)  ------1式    //为最小自然数解(最小为0)

  现在推导1式:
  对Ax%B=C 即: Ax+By=C
  d=gcd(A,B),则存在一个x1,y(可以由拓展欧几里得求出)使得 d=Ax1+By ---2式
  由"2式"两边同时模B得:d%B=Ax1%B ---3式
  又因为:C%d==0
  所以(B/d)为整数
  所以由"3式"得:C%B=(C/d)*d%B  =  (C/d)*Ax1%B=A(x1*C/d)%B
  即:C%B=A(x1*C/d)%B
  所以x=x1*(C/d)是一个整数解
  又Ax%B=C -> (A/d)x%(B/d)=C/d -> 可以看出解集为x+k*(B/d) (k=整数)
  所以最小整数解x0 = (x%(B/d)+(B/d))%(B/d) = (x1*(C/d)%(B/d)+(B/d))%(B/d)
 */

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
#define LL __int64
LL Ext_gcd(LL a,LL b,LL &x,LL &y){
    if(b==0){ x=1,y=0return a; }
    LL ret=Ext_gcd(b,a%b,y,x);
    y-=a/b*x;
    return ret;
}
//ax%n=b,求出%n范围内得到所有解,这道题用不上
vector<LL> line_mod_equ(LL a,LL b,LL n){
    LL x,y;
    LL d=Ext_gcd(a,n,x,y);
    vector<LL> ans;
    ans.clear();
    if(b%d==0){
        x=(x%n+n)%n;
        ans.push_back(x*(b/d)%(n/d));
        for(LL i=1;i<d;++i)
            ans.push_back((ans[0]+i*n/d)%n);
    }
    for(int i=0;i<ans.size();++i){
        cout<<ans[i]<<‘ ‘;
    }
    cout<<endl;
    return ans;
}
int main(){
    LL a,b,c,k;
    while(scanf("%I64d%I64d%I64d%I64d",&a,&b,&c,&k) && (a||b||c||k)){
        k=(1LL<<k);
        a=((b-a)%k+k)%k;
        LL x,y;
        LL d=Ext_gcd(c,k,x,y);
        if(a%d) puts("FOREVER");
        else{
            x=(a/d*x%(k/d)+(k/d))%(k/d);
            //line_mod_equ(c,a,k);
            printf("%I64d\n",x);
        }
    }
    return 0;
}

poj 2115 (解单变元模线性方程)

标签:algorithm   数论   

原文地址:http://blog.csdn.net/whai362/article/details/43340083

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!