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=0; return 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;

}

时间: 2024-10-21 17:31:07

poj 2115 (解单变元模线性方程)的相关文章

POJ.2065.SETI(高斯消元 模线性方程组)

题目链接 http://blog.csdn.net/Clove_unique/article/details/54381675 http://blog.csdn.net/u013081425/article/details/24299047 http://blog.csdn.net/lin375691011/article/details/38406737 https://www.cnblogs.com/IMGavin/p/5933037.html /* 模意义下的高斯消元,在初等行变换时把k=

poj 2947 Widget Factory (高斯消元,解模线性方程)

链接:poj 2947 题意:生产一些零件,已知零件种数,记录条数 记录只记录了某次生产从周几开始,周几结束,以及生产了哪些产品. 每件商品生产所需天数为3-9天. 求每样产品需要多少天才能完成. 若无解输出Inconsistent data. 有无穷解输出Multiple solutions. 有唯一解,输出其解 分析:根据题目所给信息,可以列出同余方程组,再根据高斯消元求解, 但还得判断是无解,无穷解,还是唯一解 1.系数矩阵的秩若与增广矩阵的秩不相等,则无解,否则有解 2.若有解,若增广矩

poj 2115 C Looooops (解模线性方程)

链接:poj 2115 题意:对于C语言的循环语句for(i=A ; i!=B ;i +=C), 问在k位存储系统中循环几次才会结束. 若在有限次内结束,则输出循环次数,否则输出死循环. 注:利用了 k位存储系统的数据特性进行循环(会溢出) 例如int型是16位的,那么int能保存2^16个数据, 即最大数为65535(本题默认为无符号), 当循环使得i超过65535时,则i会返回0重新开始计数 如i=65534,当i+=3时,i=1   即 i=(65534+3)%(2^16)=1 分析:设对

POJ 2115 C Looooops(模线性方程)

http://poj.org/problem?id=2115 题意: 给你一个变量,变量初始值a,终止值b,每循环一遍加c,问一共循环几遍终止,结果mod2^k.如果无法终止则输出FOREVER. 思路: 根据题意原题可化成c * x = b - a mod (2 ^ k),然后解这个模线性方程. 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio>

POJ 2115 (模线性方程 -&gt; 扩展欧几里得)

题意: for(i=A ; i!=B ;i +=C)循环语句,问在k位操作系统中循环结束次数. 若在有则输出循环次数. 否则输出死循环. 存在这样的情况:i= 65533 :i<=2:i+= 4:时i = 2: 由模线性方程->扩展欧几里得 #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <queue> using

POJ 2115 模线性方程 ax=b(mod n)

/* (x*c+a)%(2^k)==b →(x*c)%(2^k)==b-a 满足定理: 推论1:方程ax=b(mod n)对于未知量x有解,当且仅当gcd(a,n) | b. 推论2:方程ax=b(mod n)或者对模n有d个不同的解,其中d=gcd(a,n),或者无解. 定理1:设d=gcd(a,n),假定对整数x和y满足d=ax+by(比如用扩展Euclid算法求出的一组解). 如果d | b,则方程ax=b(mod n)有一个解x0满足x0=x*(b/d) mod n .特别的设e=x0+

POJ 2947 Widget Factory (高斯消元 判多解 无解 和解集 模7情况)

题目链接 题意: 公司被吞并,老员工几乎全部被炒鱿鱼.一共有n种不同的工具,编号1-N(代码中是0—N-1), 每种工具的加工时间为3—9天 ,但是现在老员工不在我们不知道每种工具的加工时间,庆幸的是还保留着一些对工人制造工具的记录,对于每个老员工,他的记录包括,他开始工作的时间(在某个星期的星期几),被炒鱿鱼的时间(某个星期的星期几),在第几个星期不知道.....在这段时间里,他正好加工了k件物品,给出了这k件物品的编号.我们要做的就是通过这些记录,来确定每种工具的加工时间是多少. 分析: 对

POJ 2947-Widget Factory(高斯消元解同余方程式)

题目地址:id=2947">POJ 2947 题意:N种物品.M条记录,接写来M行,每行有K.Start,End,表述从星期Start到星期End,做了K件物品.接下来的K个数为物品的编号. 此题注意最后结果要调整到3-9之间. 思路: 非常easy想到高斯消元. 可是是带同余方程式的高斯消元,開始建立关系的时候就要MOD 7 解此类方程式时最后求解的过程要用到扩展gcd的思想,举个样例,假设最后得到的矩阵为: 1  1   4 0  6   4 则6 * X2 % 7= 4 % 7  则

POJ 2065 SETI (高斯消元 取模)

题目链接 题意: 输入一个素数p和一个字符串s(只包含小写字母和‘*’),字符串中每个字符对应一个数字,'*'对应0,‘a’对应1,‘b’对应2.... 例如str[] = "abc", 那么说明 n=3, 字符串所对应的数列为1, 2, 3. 题目中定义了一个函数: a0*1^0 + a1*1^1+a2*1^2+........+an-1*1^(n-1) = f(1)(mod p), f(1) = str[0] = a = 1; a0*2^0 + a1*2^1+a2*2^2+....