点击打开链接
题意
1 .对于C的for(i=A ; i!=B ;i +=C)循环语句,问在k位存储系统中循环几次才会结束。
若在有限次内结束,则输出循环次数。
否则输出死循环。
思路:
2 扩展欧几里德算法源于欧几里德算法。
欧几里德算法:gcd(a,b)= gcd(b,a%b)。
证明:a可以表示成a = kb + r,则r = a mod b
假设d是a,b的一个公约数,则有d|a, d|b,
而r = a - kb,因此d|r 因此d是(b,a mod b)的公约数
假设d 是(b,a mod b)的公约数,则d | b , d |r ,但是a = kb +r
因此d也是(a,b)的公约数
因此(a,b)和(b,a mod b)的公约数是一样的,其最大公约数也必然相等,得证
3 拓展欧几里德是用来求二元一次不定方程a*x+b*y=gcd(a,b),---我们这样想 对于a'=b, b'=a%b=a-(a/b*b),
a*x+b*y=gcd(a,b)
a'*x0+b'*y0=gcd(a',b')=gcd(a,b)=a*x+b*y
b*x0+(a-a/b*b)y0=a*x+b*y
a*y0+b*(x0-a/b*y0)=a*x+b*y
所以: x=y0 ; y=x0-a/b*y0
4 若我们已经求得x0,y0为方程中x的一组特解,那么
x=x0+b/gcd(a,b)*t,y=y0-a/gcd(a,b)*t(t为任意整数)也为方程的解
x=1,y=0,因为最后是求方程a*x+0*y=a(gcd(a,0)==a),此时只要满足a=1,
y为任意值就行,对于每一个y值,最后求出的都是方程的一组解。
5 更通常的是:我们需要求解方程的最小整数解
若我们已经求得x0,y0为方程中x的一组特解,那么
x=x0+b/gcd(a,b)*t,y=y0-a/gcd(a,b)*t(t为任意整数)也为方程的解
且b/gcd(a,b),a/gcd(a,b)分别为x,y的解的最小间距,所以x在0~b/gcd(a,b)区间有且仅有一个解,
同理y在0~a/gcd(a,b)同样有且仅有一个解,这个解即为我们所需求的最小正整数解。
6 本题 :
n=2^k;
///t为 t次重复
x=([(B-A)+t*n]% n)/C; ///整除得到 x
x*C= (B-A) (mod n); ///模线性方程组
a=C ;
b=B-A;
a*x=b (mod n);
=> 所以a*x -b 是m的整数倍
=> a*x-n*y=b ;
代入 扩展 gcd即可
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #define LL long long using namespace std; void exgcd(LL a,LL b,LL &d,LL &x,LL &y) { if(b==0) { x=1;y=0; d=a; return ; } exgcd(b,a%b,d,x,y); int t=x; x=y; y=t-(a/b)*y; } int main() { LL A,B,C,D; while(~scanf("%lld%lld%lld%lld",&A,&B,&C,&D)) { if(!A&&!B&&!C&&!D) break; LL d,x,y; LL a=C,b=B-A; LL n=((LL)1)<<D; exgcd(a,n,d,x,y); if(b%d!=0) ///方程 ax=b(mod n)无解 printf("FOREVER\n"); else { x=(x*(b)/d)%n; ///方程右边值比 x=(x%(n/d)+n/d)%(n/d); ///方程ax=b(mod n)的最小整数解 printf("%lld\n",x); } } return 0; }