75-扩展GCD-时间复杂度

扩展gcd-时间复杂性

题目内容:
计算循环语句的执行频次 for(i=A; i!=B ; i+=C) x+=1;
其中A,B,C,i都是k位无符号整数。
输入描述
A B C k, 其中0<k<32
输出描述
输出执行频次数,如果是无穷,则输出“forever”
输入样例
3 7 2 16
输出样例2
看到题还是很蒙蔽,虽然提示了知识点:
gcd(a,b)为求a,b的最大公约数;
ex_gcd(a,b,x,y)则是求 ax + by = gcd(a,b)的一组解
由ax + by = gcd(a,b) 和 ax1 + by1 = c 就可以求后一个方程的解了:x1 = x * (n / gcd(a,b)), y1 = y * (n / gcd(a,b));
但注意:先计算Gcd(a,b),若c不能被Gcd(a,b)整除,则方程无整数解
此时 x1,y1只是方程 ax + by = c的一组解,他们的通解为
x = x0 + tn;
y = y0 - tm;
(x0, y0为最正小整数解)
则有 a(x0 + tn) + b(y0 - tm) = c,同时又有ax0 + by0 = c,化简上式子:
a*t*n - b*t*m = 0;

则 an = bm 要想n,m最小就是使得an,bm都为a,b的最小公倍数:
an = (a*b)/gcd(a,b) -> n = b/gcd(a,b);
同理:m = a /gcd(a,b);
则:x0 = (x % n + n)%n;
y0 = (y % m + m)%m;

#include <iostream>
#include <algorithm> 
#include <cmath>
using namespace std;
//#define LL long long
typedef long long LL;
LL gcd(LL a, LL b)
{
	return b == 0 ? a : gcd(b, a%b);
}
 
LL ex_gcd(LL a, LL b, LL &x, LL &y)
{
	if (b == 0)
	{
		x = 1;
		y = 0;
		return a;
	}
	LL ans = ex_gcd(b, a%b, x, y);
	LL temp = x;
	x = y;
	y = temp - a / b*y;
	return ans;
}

int main(){
	LL A, B, C, k;
	cin >> A >> B >> C >> k;
	LL a = C,  n = B - A, x, y; //b = pow(2,k),
	//b改成b = 1 << k就会出错
	LL d = 1;
	LL b = d << k; 
	cout << "b: " << b << endl;
	int gc = gcd(a,b);
	if(A == 0 && B == 0){
		cout << 0 << endl;
		return 0;
	} 
	if(C == 0 || gc == 0 || n % gc != 0){
		cout << "forever" << endl;
		return 0;
	}
	ex_gcd(a,b,x,y);    //返回ax + by = gcd(a,b)的解 
	x = x * (n / gc);   //得到通解x即:ax + by = n 
	LL nn = b / gc;     //通解x的最小周期 
	x = (x % nn + nn) % nn; //得到最小解 
	cout << x << endl;
	return 0;
} 
 
    

  








 

转载于:https://www.cnblogs.com/zhumengdexiaobai/p/9493267.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值