拓展欧几里德 (附 POJ 2115)
来源:互联网 发布:淘宝卖家如何主动退款 编辑:程序博客网 时间:2024/06/01 03:58
关于拓展欧几里德,别人已经写的很好的了,我也自己写一下,方便以后自己复习。
其最基础的思想就是 gcd(a,b)=gcd(b,a mod b),其中 gcd的意思是求最大公约数。。
拓展欧几里德是用来求 x,y 是的a*x+b*y=gcd(a,b),---我们这样想 对于a'=b, b'=a%b=a-(a/b*b),
a*x+b*y=gcd(a,b)
a'*x0+b'*y0=gcd(a',b')=gcd(a,b)=a*x+b*y
b*x0+(a-a/b*b)y0=a*x+b*y
a*y0+b*(x0-a/b*y0)=a*x+b*y
所以: x=y0 ; y=x0-a/b*y0;
所以 拓展欧几里德的函数为
int extended_euclid(int s,int t,int &x,int &y){if(t==0){x=1;y=0 return s;}else {int i=extended_euclid(t,s%t);int temp=x;x=y;y=temp-(s/t*y);}return i;}
用此思想求线性同余方程:a*x+b*y=n ; (有整数解的充要条件是 (n%(a,b)==0) )
我们可以先求出一组x0,y0 是的a*x0+b*y0=(a,b)
然后 等号左右同时除以(a,b) 得: a*x0/(a,b)+b*y0/(a,b)=1
接着等号左右同时乘以 n 就得到 : a*x0/(a,b)*n + b*y0/(a,b)*n=n
所以 得到: x=x0/(a,b)*n y=y0/(a,b)*n 为方程的一组解了。
若 (a,b)=1 且 x0,y0,为方程 a*x+b*y=n的一组解 ,那么 x=x0+b*t ,y=y0-a*t (t为任意整数)都是方程的解。
而往往题目中要求求最小的解,那么我们就可以将一个特解x,t=b/(a,b),x=(x%t+t)%t;就可以了。
poj 2115
Description
for (variable = A; variable != B; variable += C) statement;
I.e., a loop which starts by setting variable to value A and while variable is not equal to B, repeats statement followed by increasing the variable by C. We want to know how many times does the statement get executed for particular values of A, B and C, assuming that all arithmetics is calculated in a k-bit unsigned integer type (with values 0 <= x < 2k) modulo 2k.
Input
The input is finished by a line containing four zeros.
Output
Sample Input
3 3 2 163 7 2 167 3 2 163 4 2 160 0 0 0
Sample Output
0232766FOREVER
分析:题目给出 a,b,c,k,且1<=a,b,c<=2^k; 求最小的x ,使得 ( a+c*x ) mod 2^k = b。
喵呜的推导: a+c*x=b mod 2^k
即: a+c*x= b (mod 2^k)
即: a+c*x-b |2^k
所以存在t 使得 : t*2^k =a+c*x-b;
所以: t*2^k-c*x=a-b;
然后用 拓展欧几里德的思想做即可。。。
代码:
#include <iostream>#include <stdio.h>#include <math.h>using namespace std;__int64 n,x,y;__int64 extended_euclid(__int64 s,__int64 t) //拓展欧几里德算法{__int64 i,temp; if(t==0) { x=1; y=0; return s; }else { i=extended_euclid(t,s%t); temp=x; x=y; y=temp-(s/t*x);}return i;}int main(){ __int64 a,b,c,i,j,e,m,k,d; while(scanf("%I64d%I64d%I64d%I64d",&a,&b,&c,&k)) { if(a==0 && b==0 && c==0 && k==0) break; d=(__int64)1<<k; //超过30位的要定义1为 64 位,看discuss里面才知道的。。。 e=extended_euclid(c,d); if((b-a)%e) printf("FOREVER\n"); else { a=x*(b-a)/e%d+d; //公式推导。 printf("%lld\n",a%(d/e)); //求最小的那个 要 mod (d/e) } } return 0;}
- 拓展欧几里德 (附 POJ 2115)
- poj 2115 拓展欧几里德
- poj 2115 C Looooops 拓展欧几里德定理
- POJ 2115 C Looooops(拓展欧几里德)
- POJ 1061 :拓展欧几里德
- POJ 1061 拓展欧几里德算法
- PKU 2115 C Looooops(拓展欧几里德)
- poj 2115 C Looooops 拓展欧几里德 解模线性方程模板
- poj 1061 青蛙的约会(拓展欧几里德)
- POJ 1064 青蛙的约会(拓展欧几里德算法)
- POJ 1061 青蛙的约会 拓展欧几里德
- 拓展欧几里德
- 拓展欧几里德
- 欧几里德与拓展欧几里德
- zoj Modular Inverse 3609 (拓展欧几里德)
- NEFU 84 五指山(拓展欧几里德)
- POJ 2115 C Looooops(扩展欧几里德)
- poj 2115||zoj2305(扩展欧几里德)
- HDU 3917 Road constructions 2011 Multi-University Training Contest 8 - Host by HUST 最大权闭包
- How to debug codec code on DM6467T EVM
- syntax error : missing ';' before 'type'原因探寻
- Delphi 函数指针 过程/函数类型
- 安装tcpdump
- 拓展欧几里德 (附 POJ 2115)
- read xml
- 数据库有什么好处
- thread.join()用法及例子
- Tcpdump的安装和使用
- my life
- 重访AlertDialog和AlertDialog.Builder
- Linux启动界面切换:图形界面-字符界面(转)
- openSUSE: 在Linux下安装Wireshark,经典协议分析器