poj 2115 C Looooops(扩展欧几里德算法)

 题意:

       对于for(i=A ; i!=B ;i+=C)循环语句,问在k位存储系统中循环几次才会结束。
  比如:当k=4时,存储的数 i 在0-15之间循环。(本题默认为无符号)

  若在有限次内结束,则输出循环次数。

  否则输出死循环。

二,思路:
本题利用扩展欧几里德算法求线性同余方程,设循环次数为 x ,则解方程 (A + C*x) % 2^k = B;求出最小正整数 x。 
  1,化简方程化为求线性同余方程标准式 ax ≡ b (mod n);
  2,扩展欧几里德算法求解线性同余方程 C*x ≡ B-A (mod 2^k);上面的红色公式转化为这个式子没有看懂(两者之间的转化)
  3,求出最小非负整数解。

1、化简:(A + C*x) mod 2^K = B  -->  C*x mod 2^k = B-A  -->   C*x ≡ B-A (mod 2^k);  

(A+x*C)%(2^k)=B 变形(2^k)*y+B=A+C*x ==>  C*x+(-(2^k)*y)=B-A;这个变形比较实用吧

2、求线性同余方程 C*x ≡ B-A (mod 2^k) ,

就相当于求二元一次方程 C*x + 2^k * y = B-A 

  i,代入扩展欧几里德算法,求解方程 C*x + 2^k * y = gcd(C , 2^k) ; 

  ii,利用方程 C*x + 2^k * y = gcd(C , 2^k)的解 x0 和x1 = x0 * c/d 求出原方程 a*x + b*y = c 的解 x1 ;前提是:d|c (c 能被 d 整除);

3、利用周期性变化求最小的非负整数解 公式: x1 = (x1 % (b/d) + (b/d) ) % (b/d);
      若方程的C*x + 2^k * y = B-A 的一组整数解为(x1 , y1),则它的任意整数解为(x1 + k * (b/d) , y1 - k * (a/d) ) ( k取任意整数 ), T = b/d就为 x1 增长的周期 
     i,若x1为负值,取最大的非正值:x1 = x1 % T ; 若x1为正值,以下两步无影响; 
     ii,取正 :x1 = x1 + T ;

     iii, 防止 i 中的 x1=0 即 ii 中的 x1=T :x1 = x1 % T ;

看到数论概论中的得到的一些总结(和上面的(2)ii类似:

已知ax+by=1的一组解为(x1,y1),那么其他组的解为(x1+k*b,y1-k*a)(k为任意整数) 

当ax+by=gcd(a,b)=d时,其他组的解变为(x1+k*b/d,y1-k*a/d),因此b/d就成为了一个增长周期

#include <iostream>
using namespace std;
void exgcd(long long a,long long b,long long &d,long long &x,long long &y)
{
	if(!b)//b==0说明上层a%b==0上层的b(这层的a)为最大公因数,则a*x+b*y=a
	{
		d=a; 
		//递归到这时候a就是最大公因数( d用来存储gcd(a,b)的值)
		//结合上一层exgcd(b,a%b,d,y,x)
		x=1;
		y=0;
	}
	else
	{
		exgcd(b,a%b,d,y,x);
		y=y-x*(a/b);//...........
	}
}
int main()
{
	long long A,B,C,x,y,T,d;
	int k;
	while(cin>>A>>B>>C>>k&&(A+B+C+k))
	{
		long long n=1LL<<k;//n = 1 * 2^k ;
		exgcd(C,n,d,x,y);//a*x + b*y = c ,C*x + 2^k * y =B-A
			if((B-A)%d!=0)//上面(2)中的性质ii
			{
				cout<<"FOREVER"<<endl;
				continue;
			}
			x=x*(B-A)/d;
			T=n/d;
			x=(x%T+T)%T;
			cout<<x<<endl;
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值