POJ 2115 Looooops (扩展欧几里得+调整解)
来源:互联网 发布:阿里丁丁 mac 编辑:程序博客网 时间:2024/06/14 15:12
题目大意:
给出一组数 a b c k,问 a + mc = b(mod 2^k)的解m是多少,若有解,则输出最小正解的大小,若没有,输出FOREVER,表明a永远无法通过加c的方式得到b的值。
解题思路:
根据刚才列出的式子可以很容易的发现,此题可以直接使用扩展欧几里得算法求解,扩展欧几里得算法用于求解形如 ax+by=d=gcd(a,b)的方程,求得的解x和y满足x+y的和最小。
由欧几里得算法可知 gcd(a,b)=gcd(b,a%b)(证明略)
我们可以列出另一个方程:
bx1+(a%b)y2=d=gcd(b,a%b)=gcd(a,b)=ax1+by1
即:bx+(a-a/b*b)y=ax+by
展开可得: a * y2 + (x - a/b*y2)b = a * x1 + b * y1
由等式两边的对应关系可得:y2 = x1 , y1 = x - a/b * y2
由这个过程递推到gcd(a,b)= 1 将产生的 x 和 y 收集起来 即为这个二元一次方程的整数解集。
由上述推导,我们可以构造出一个式子:
x * C + y * 2^k = b - a = p * d = p * gcd( C,2^k)
带入扩展欧几里得算法解出系数即可,注意这里的系数还需要乘上系数,也就是 b-a 是 C,2^k 的最大公约数的正整数倍,所以还需要乘上系数。
题目中有一个坑点:扩展欧几里得算法求解出的系数是满足x+y最小的,而题目中要求我们求出的是 x 的最小值,所以需要在适当的范围内对x的值进行调整使得其成为最小的正整数解。
由于方程的解必须为整数,我们求得的解也为整数,所以应该在解的基础上减去解的分布周期, 由最初始的式子 a * x +b*y= d 可以发现,在 ax 减小的大小等于 by 增加的大小,这个值刚好是 a b 的最小公倍数,而 a b 的最小公倍数是 a b 的乘积除以最大公约数 d ,即(a * b / d)。这样我们就得到了周期,在调整的过程中要注意,方程求解会得到 x 小于 0 的解,因此只需对负数解的情况稍加判断就可以正确的AC此题了。
希望大家都能快速AC,并搞懂扩展欧几里得内部的证明和原理!
附上代码:
#include <cstdio>#include <algorithm>#include <cstring>#include <iostream>using namespace std;typedef long long int lli;lli mi[35];void init(){ mi[0]=1; for(int i=1;i<=32;i++) mi[i]=2*mi[i-1];}lli exgcd(lli a,lli b,lli &x,lli &y){ if(b==0) { x=1; y=0; return a; } lli ans=exgcd(b,a%b,x,y); lli temp=x; x=y; y=temp-a/b*y; return ans;}int main(){ lli A,B,C,k,x,y; init(); lli num,key,sum,temp; while(~scanf("%lld%lld%lld%lld",&A,&B,&C,&k),(A+B+C+k)) { num=B-A; key=exgcd(C,mi[k],x,y); if(num<0) num+=mi[k]; if(num%key!=0) printf("FOREVER\n"); else { temp=mi[k]/key; sum=x*num /key; sum %= temp; while(sum < 0) sum += temp; printf("%lld\n",sum); } } return 0;}
- POJ 2115 Looooops (扩展欧几里得+调整解)
- POJ 2115 C Looooops 解模线性方程(扩展欧几里得)
- POJ 2115 C Looooops(扩展欧几里得)
- poj 2115 C Looooops(扩展欧几里得)
- poj-2115 C Looooops(扩展欧几里得)
- poj 2115 C Looooops (扩展欧几里得)
- POJ 2115 C Looooops 扩展欧几里得算法
- poj 2115 C Looooops 扩展欧几里得
- POJ - 2115 - C Looooops (扩展欧几里得)
- POJ 2115 C Looooops(扩展欧几里得)
- POJ 2115 C Looooops(扩展欧几里得)
- poj 2115 C Looooops 【扩展欧几里得】
- POJ 2115 C Looooops (扩展欧几里得)
- poj 2115 C Looooops (扩展欧几里得算法)
- POJ-2115-C Looooops(扩展欧几里得)
- C Looooops poj 2115 扩展欧几里得
- [poj 2115] C Looooops 扩展欧几里得
- poj 2115 C Looooops (扩展欧几里得)
- linux
- 良心老板
- 一个小实战
- 图文比较八种排序算法
- 生成pdf的三种方法差异
- POJ 2115 Looooops (扩展欧几里得+调整解)
- iOS开发 UITest的使用
- Android 满屏隐藏虚拟键盘
- angular js Filter
- 二层三层转发学习
- JS判断客户端是否是iOS或者Android手机移动端
- ZCMU-1404-Computers
- Hadoop 入门
- 将博客搬至CSDN