POJ 2115 C Looooops (拓展的欧几里得) 拓展的欧几里得详解
来源:互联网 发布:啄木鸟审计软件 编辑:程序博客网 时间:2024/06/06 04:10
Description
A Compiler Mystery: We are given a C-language style for loop of type
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.
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 consists of several instances. Each instance is described by a single line with four integers A, B, C, k separated by a single space. The integer k (1 <= k <= 32) is the number of bits of the control variable of the loop and A, B, C (0 <= A, B, C < 2k) are the parameters of the loop.
The input is finished by a line containing four zeros.
The input is finished by a line containing four zeros.
Output
The output consists of several lines corresponding to the instances on the input. The i-th line contains either the number of executions of the statement in the i-th instance (a single integer number) or the word FOREVER if the loop does not terminate.
Sample Input
3 3 2 163 7 2 167 3 2 163 4 2 160 0 0 0
Sample Output
0232766FOREVER
题目大意:根据题意求出循环次数,若死循环输出FOEVER
思路:通过公式的变形可得C*x=(B-A)%2^k转化为模的线性方程
</pre><pre name="code" class="cpp">#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>#include<cmath>#define LL long long#define inf 0x3f3f3f3fusing namespace std;LL x,y;LL exgcd(LL a,LL n){ LL t,d; if(!n)//已知方程a*x+b*y=gcd(a,b){ 公式一 };这里n-->b { x=1;y=0;//当n==0,a*x=gcd(a,0)=a;所以x=1,y=0; return a; }//否则继续进行 d=exgcd(n,a%n);//当再次递归时gcd(a,n)=gcd(n,a%n),将其带入公式1中变形可得 //b*x1+(a%b)*y1==b*x1+(a-(a/b)*b)*y1==a*y1+b*(x1-(a/b)*y1),最终得到ax+by==a*y1+b*(x1-(a/b)*y1) t=x;//既可以得到x=y1(y),y1(y)=x1-(a/b)*y1 x=y; y=t-a/n*y; return d;}int main(){ LL n,k,i,j,A,B,C,a,b,d; while(~scanf("%lld%lld%lld%lld",&A,&B,&C,&k)) { if(A==0&&B==0&&C==0&&k==0)//已知拓展的欧几里得公式为ax+by=gcd(a,b); break; n=(1LL<<k);//若不再1后加LL会WA- -! a=C;b=B-A;//根据题意,可以推得C*x=(A-B)%2^k;此方程为模线性方程即a*x=b%n; d=exgcd(a,n); if(b%d)//模线性方程有解的充要条件是b%(gcd(a,n))==0 { puts("FOREVER"); continue; }//如果线性方程 x=x*(b/d)%n;//方程a*x=b%n的最小解 x=(x%(n/d)+(n/d))%(n/d);// x%(n/gcd(a,n))使解落到区间-n/gcd(a,n)~n/gcd(a,n), //再加上n/gcd(a,n)使解在区间0~2*n/gcd(a,n),//再模上n/gcd(a,n),则得到最小整数解 printf("%lld\n",x); } return 0;}
思路:扩展的欧几里得为ax+by=c => 一、ax+by=GCD(a,b) , 通过此题二、Cx+my=B-A,同时 我们还可以得到公式 Cx+A+y2^k=B 即Cx=(B-A)%2^k
我们可以吧b=(B-A); 通过ex扩展GCD公式求出x,注意这里的x不是公式二Cx+my=b中的x,若想由公式一中的推出公式二可以将公式一同时乘b/GCD(C,2^k);
这就是为什么x=x*(b/GCD()).还有x取得范围问题,(x0+k*(m/GCD()) ,y0+k*(C/GCD()));(T_T终于明白了!!!!!)
#include<map>#include<queue>#include<cmath>#include<iostream>#include<cstdio>#include<stack>#include<cstring>#include<algorithm>#define LL __int64#define inf 0x3f3f3f3fconst double PI=acos(-1.0);using namespace std;void ex(LL a,LL b,LL &d,LL &x,LL &y){ if(!b){ d=a,x=1,y=0; } else{ ex(b,a%b,d,y,x); y-=x*(a/b); }}int main(){ LL b,B,A,C,n,k,d,x,y; while(~scanf("%I64d%I64d%I64d%I64d",&A,&B,&C,&k)){ if(!A&&!B&&!C&&!k) break; n=(1LL<<k); b=B-A; ex(C,n,d,x,y); if(b%d==0){ x=x*(b/d)%n; x=(x%(n/d)+n/d)%(n/d); printf("%I64d\n",x); } else{ puts("FOREVER"); } } return 0;}
1 0
- POJ 2115 C Looooops (拓展的欧几里得) 拓展的欧几里得详解
- POJ - 2115 C Looooops(拓展欧几里得)
- POJ 2115 C Looooops 拓展欧几里得
- POJ 2115 C Looooops(拓展欧几里得)
- poj C Looooops 类似青蛙的约会,拓展欧几里得算法
- poj C Looooops 2115 (拓展欧几里得+数学)
- POJ 2115 C Looooops——拓展欧几里得算法
- 20140714 「初等数论 - 拓展欧几里得+同余模方程」POJ 2115 C Looooops
- 拓展的欧几里得算法
- 拓展的欧几里得
- 拓展的欧几里得算法
- POJ2115C Looooops(拓展欧几里得)
- [拓展欧几里得] poj 1061 青蛙的约会
- POJ 1061 青蛙的约会【拓展欧几里得】
- Poj 1061 青蛙的约会【拓展欧几里得】
- poj 1061 青蛙的约会 拓展欧几里得
- POJ.1061 青蛙的约会 (拓展欧几里得)
- POJ 1061青蛙的约会(拓展欧几里得)
- 查找输入整数二进制中1的个数
- oldssoj2674Delicious Apples(离散+贪心+环上折半dp)
- Android-实现图片的简单特效(平移、缩放、旋转、镜面、倒影)
- poj 1321 DFS
- 抽象类和抽象方法
- POJ 2115 C Looooops (拓展的欧几里得) 拓展的欧几里得详解
- Cocos2d-x 移植到 Windows10 环境搭建
- 剑指offer面试题java实现之题7之相关题目:用两个队列实现一个栈
- github备忘(linux下)
- Python中if __name__='__main__':的解析
- 小岛上的蓝眼睛的人要几天才能全部离开
- shader 编程工具:NVIDIA FX Composer和Render Monkey
- Java(十四)--创建窗口,添加按钮,接受事件
- Android的HTTP客户端选择及HttpResponseCache的使用