POJ 2115 C Looooops(扩展欧几里得)
2015-07-26 22:13
309 查看
辗转相除法(欧几里得算法)
时间复杂度:在O(logmax(a, b))以内
扩展欧几里得算法
时间复杂度和欧几里得算法相同
用于求ax+by=gcd(a,b)整数解,xy返回整数解,extgcd的返回值是ax+by的值。
题目:(A+x*C)%2^k=B 求x整数解。
解析:
x*C=B-A 的在mod(2^k)情况下的整数解
可以转化成x*C+y*(2^k)=B-A的解
通过扩展欧几里得算法求出x1*C+y1*(2^k)=gcd(c,2^k)的解x1,y1,d=x1*C+y1*(2^k)=gcd(c,2^k)
x1*C+y1*(2^k)=(B-A)(gcd(c,2^k)/(B-A))
(A-B)/gcd(c,2^k)*x1*C+(A-B)/gcd(c,2^k)*y1*(2^k)=B-A
x=(A-B)/gcd(c,2^k)*x1
y=(A-B)/gcd(c,2^k)*y1
要求的值为x,x可能是负数,所以要把x变到正整数。通过+(2^k)/d 再%(2^k)/d来变成正数。
时间复杂度:在O(logmax(a, b))以内
int gcd(int a, int b) { if (b == 0) return a; return gcd(b, a % b); }
扩展欧几里得算法
时间复杂度和欧几里得算法相同
int extgcd(int a, int b, int& x, int& y) { int d = a; if (b != 0) { d = extgcd(b, a % b, y, x); y -= (a / b) * x; } else { x = 1; y = 0; } return d; }
用于求ax+by=gcd(a,b)整数解,xy返回整数解,extgcd的返回值是ax+by的值。
题目:(A+x*C)%2^k=B 求x整数解。
解析:
x*C=B-A 的在mod(2^k)情况下的整数解
可以转化成x*C+y*(2^k)=B-A的解
通过扩展欧几里得算法求出x1*C+y1*(2^k)=gcd(c,2^k)的解x1,y1,d=x1*C+y1*(2^k)=gcd(c,2^k)
x1*C+y1*(2^k)=(B-A)(gcd(c,2^k)/(B-A))
(A-B)/gcd(c,2^k)*x1*C+(A-B)/gcd(c,2^k)*y1*(2^k)=B-A
x=(A-B)/gcd(c,2^k)*x1
y=(A-B)/gcd(c,2^k)*y1
要求的值为x,x可能是负数,所以要把x变到正整数。通过+(2^k)/d 再%(2^k)/d来变成正数。
#include <cstdio> long long extgcd(long long a, long long b, long long& x, long long& y) { long long d = a; if (b != 0) { d = extgcd(b, a % b, y, x); y -= (a / b) * x; } else { x = 1; y = 0; } return d; } int main() { long long a, b, c, k; while (scanf("%lld%lld%lld%lld", &a, &b, &c, &k) != EOF) { if (a == 0 && b == 0 && c == 0 && k == 0) break; long long x, y; long long t = b - a; long long h = 1LL << k; //2^k long long g = extgcd(c, h, x, y); if (t % g != 0) { //no solution printf("FOREVER\n"); continue; } x *= t / g; x = (x % (h / g) + (h / g)) % (h / g);//最小非负整数解 printf("%lld\n", x); } return 0; }
相关文章推荐
- 1.7-linux启动流程
- Linux 下编译安装 PHP 5.6
- Linux显示文件命令之cat/tac
- nginx初探
- 对同一类型的控件的统一监控
- shell的特殊变量及如何查看当前shell
- SHELL--基本语法
- block作为类的属性时用copy
- hadoop 2.6.0 安装及实例 详细有截图
- SHELL--基本命令
- 微软测试网站
- Linux 使用core file文件快速定位程序崩溃代码行
- OpenGL教程翻译 第十一课 Concatenating Transformations
- OpenGL教程翻译 第九课 插值
- Linux常用命令之seq/rm
- Linux中断处理驱动设计
- OpenGL教程翻译 第十课 索引绘制
- OpenGL教程翻译 第七课 旋转变换
- linux删除文件未释放空间问题处理
- OpenGL教程翻译 第八课 缩放变换