poj2115-Looooops-(扩展欧几里得定理)

C Looooops
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions:33752   Accepted: 9832

Description

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
翻译:在循环里,values值为a,每次加c,如果values不等于b,就继续循环下去,死循环输出forever,否则输出循环次数。所有运算都对无符号的k位二进制求模。
解题过程
设p=2^k
起点为a,每次加c,对p求模若能等于b对p求模则有解,否则无解,输出forever
有解的话设解为x
(a+cx)%p = b%p
a%p + cx%p = b%p
cx%p = (b-a)%p
cx%p + 0 = (b-a)%p
cx%p + yp%p = (b-a)%p
形如ax+by=gcd,扩展欧几里得定理。
 1 #include<stdio.h>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<math.h>
 6 #include<string>
 7 #define ll long long
 8 #define inf 0x3f3f3f3f
 9 using namespace std;
10 // ax + by = gcd(a,b)
11 ll exgcd(ll a, ll b, ll &x, ll &y)//扩展欧几里德定理
12 {
13     if(b==0)//终有一次a%b传进来是0,递归出口
14     {
15         x=1;
16         y=0;
17         return a;
18     }
19     ll q=exgcd(b,a%b,y,x);
20     //最终递归出来,y1=1,x1=0
21     y=y-(a/b)*x;
22     //后面的y相当于下一个递归的x2,x相当于下一个递归的y2,符合推导公式
23     //x1=y2;   y1=x2-[a/b]*y2;
24     return q;
25 }
26 
27 int main()
28 {
29     ll a,b,c,k,p,x,y;
30     while(scanf("%lld %lld %lld %lld",&a,&b,&c,&k)!=EOF&&(a+b+c+k))
31     {
32         p=1;
33         for(ll i=1;i<=k;i++)
34             p=p*2;
35         ll gcd=exgcd(c,p,x,y);
36         ll d=b-a;
37         if(d%gcd)
38             printf("FOREVER
");
39         else
40         {
41             ll  multiple=d/gcd;///倍数
42             p=p/gcd;///通解公式:x=x+b/gcd y=y-a/gcd
43             x=( (x*multiple)%p+p )%p;///求最小正数解
44             printf("%lld
",x);
45         }
46     }
47     return 0;
48 }
原文地址:https://www.cnblogs.com/shoulinniao/p/10361943.html