题目地址:C Looooops
题目大意:
有一个for循环:for(i=A;A!=B;A+=C) 从A开始每次加上C问至少循环多少次等于B,在K位的储存系统中的特性:
例如int型是16位的,那么int能保存2^16个数据,即最大数为65535(本题默认为无符号), 当循环使得i超过65535时,则i会返回0重新开始计数 如i=65534,当i+=3时,i=1 其实就是 i=(65534+3)%(2^16)=1
如果循环不到B 则输出死循环。
解题思路:
扩展欧几里德。
推出解析方程:
设循环x次: n=2^k。 x=(((B-A)+n)%n) /C C*x=(B-A)%n C*x+n*y=B-A
然后看GCD(C,n) 能否被(B-A)整除。则符合扩展欧几里德。
然后通过扩展欧几里德求出X0和Y0 。
所以方程:C*x+n*y=GCD(C,n)的通解为:X0+n/GCD(C,n)*K、Y0-C/GCD(C,n)*K。
举例说明:
例如: 2x+4y=6 求出 x0=1、y0=1. 通解为:1+(4/2)*k 和 1-(2/2)*k。 因为代入方程k刚好消去。 之所以除以(2,4)的最大公约数,是因为如果不除会漏掉一些解,例如:漏去3、0
所以方程:C*x+n*y=B-A 的通解为 X0*GCD(C,n)+n/GCD(C,n)*K、Y0*GCD(C,n)-C/GCD(C,n)*K。
所以求出最小正整数解X= (X0*GCD(C,n)%(n/GCD(C,n))+n/GCD(C,n))%(n/GCD(C,n))。
代码:
1 //解析式方程 B-A=C*x+n*y 2 #include <algorithm> 3 #include <iostream> 4 #include <sstream> 5 #include <cstdlib> 6 #include <cstring> 7 #include <cstdio> 8 #include <string> 9 #include <bitset> 10 #include <vector> 11 #include <queue> 12 #include <stack> 13 #include <cmath> 14 #include <list> 15 //#include <map> 16 #include <set> 17 using namespace std; 18 /***************************************/ 19 #define ll long long 20 #define int64 __int64 21 #define PI 3.1415927 22 /***************************************/ 23 const int INF = 0x7f7f7f7f; 24 const double eps = 1e-8; 25 const double PIE=acos(-1.0); 26 const int d1x[]= {0,-1,0,1}; 27 const int d1y[]= {-1,0,1,0}; 28 const int d2x[]= {0,-1,0,1}; 29 const int d2y[]= {1,0,-1,0}; 30 const int fx[]= {-1,-1,-1,0,0,1,1,1}; 31 const int fy[]= {-1,0,1,-1,1,-1,0,1}; 32 const int dirx[]= {-1,1,-2,2,-2,2,-1,1}; 33 const int diry[]= {-2,-2,-1,-1,1,1,2,2}; 34 /*vector <int>map[N];map[a].push_back(b);int len=map[v].size();*/ 35 /***************************************/ 36 void openfile() 37 { 38 freopen("data.in","rb",stdin); 39 freopen("data.out","wb",stdout); 40 } 41 priority_queue<int> qi1; 42 priority_queue<int, vector<int>, greater<int> >qi2; 43 /**********************华丽丽的分割线,以上为模板部分*****************/ 44 45 long long exgcd(long long a,long long b,long long &x,long long &y) 46 { 47 if (b==0) 48 { 49 x=1; 50 y=0; 51 return a; 52 } 53 else 54 { 55 long long r=exgcd(b,a%b,x,y); 56 long long t=x; 57 x=y; 58 y=t-a/b*y; 59 return r; 60 } 61 } 62 int main( ) 63 { 64 long long a,b,c,k; 65 while(scanf("%lld%lld%lld%lld",&a,&b,&c,&k)!=EOF) 66 { 67 if (a==0&&b==0&&c==0&&k==0) 68 break; 69 long long z=b-a,p=c; 70 long long q=1LL<<k; 71 long long x,y; 72 long long g=exgcd(p,q,x,y); 73 if (z%g!=0) 74 printf("FOREVER "); 75 else 76 { 77 q=q/g; 78 x*=(z/g); 79 x=(x%q+q)%q; 80 printf("%lld ",x); 81 } 82 } 83 return 0; 84 }