(模板题)poj 2115 C Looooops(扩展欧几里得算法)
2016-08-18 20:53
330 查看
C Looooops
A Compiler Mystery: We are given a C-language style for loop of type 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. 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 16 3 7 2 16 7 3 2 16 3 4 2 16 0 0 0 0 Sample Output 0 2 32766 FOREVER Source CTU Open 2004 |
提示
题意:给出A,B,C(0<=A,B,C<2^k),k(1<=k<=32)。经过几次循环才能使A=B,用for循环写成:for(i=A;B!=i;i=i+C),如果数值超出2^k,那就像电脑从0开始计数,比如k=2,运行后A变成5,那么2^2<5,5转化为1。如果永远不能跳出循环输出"FOREVER"。
思路:
首先我们可以写出Cx=(B-A+2^k)%2^k
x=(B-A+2^k)%2^k/C
之后。。。还是不能得出答案
因为有不能跳出循环这一情况,需要用扩展欧几里得算法(来源于书):
形如ax+by=c的不定方程称为二元一次不定式方程。显然(1)a=0或b=0时,方程的解确定。(2)c不是gcd(a,b)的倍数时,方程无解。
因此,只考虑ab!=0且gcd(a,b)能整除c的情况。
求最大公约数的过程:
r0=r1*q1+r2
r1=r2*q2+r3
......
rk-1=rk*qk
由倒数第二个式子往回推演,将倒数第二个式子变形得到
gcd(a,b)=rn-1*x1+rn-2*y1
联立倒数第三个式子消去rn-1得到
gcd(a,b)=rn-2*x2+rn-3*y2
以此类推,一直得到
gcd(a,b)=a*x+b*y
如此便得出了ax+by=gcd(a,b)的解,那么c是gcd(a,b)的倍数时的解也就很明显了。
那么要怎么套呢?
刚推出的方程简化为Cx=(B-A)mod2^k,这里我们称x是关于2^k的乘法逆元,表达式等价与Cx+(2^k)*y=(B-A)。
之后就好做了吧。
扩展欧几里得详解。
示例程序
Source Code Problem: 2115 Code Length: 760B Memory: 388K Time: 0MS Language: GCC Result: Accepted #include <stdio.h> long long x,y; long long f(long long a,long long b) { long long t,d; if(b==0) { x=1; y=0; return a; } d=f(b,a%b); t=x; x=y; y=t-a/b*y; return d; } int main() { long long k,i,d,A,B,C,a,b,c; scanf("%lld %lld %lld %lld",&A,&B,&C,&k); while(A!=0||B!=0||C!=0||k!=0) { b=1; for(i=1;k>=i;i++) { b=b*2; } a=C; c=B-A; d=f(a,b); //扩展欧几里得算法 if(c%d!=0) { printf("FOREVER\n"); } else { x=(x*c/d)%b; //完全循环一次就够了,所以有c/d b=b/d; x=(x%b+b)%b; //因为都是非负数所以要进行转化 printf("%lld\n",x); } scanf("%lld %lld %lld %lld",&A,&B,&C,&k); } return 0; }
相关文章推荐
- POJ 2115 C Looooops 扩展欧几里得算法
- POJ 2115 C Looooops <扩展欧几里得算法>
- poj 2115 C Looooops 拓展欧几里德 解模线性方程模板
- [数论]POJ 2115/HOJ 1787 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
- 20140714 「初等数论 - 拓展欧几里得+同余模方程」POJ 2115 C Looooops
- POJ 2115 C Looooops(扩展欧几里得)
- 【数论】 POJ 2115 C Looooops
- POJ-2115 C Looooops 扩展GCD