POJ2115 C looooops 【求解线性同余方程】

执行了X次后

C*x+y*2^k=B-A

从A到B

本质就是求同余方程

C*x=B-A    mod    2^k

 

 

注意k的范围是32,超过int了,全用longlong

 

接下来就是求同余方程那一套了

 

a*x+b*y=gcd(a,b)这个扩展欧几里德算法解出来的x是最小的

 

还有

第一步后,方程式变为

gcd=gcd(C,2^k)

C*x/gcd+y*2^k/gcd=(B-A)/gcd

(C*x)/gcd=(B-A)/gcd    mod    2^k/gcd

 

这时候x可能得到负数,但是要在2^k/gcd范围内模成正数(道理很简单,C和2^k同时缩短gcd倍,步长和路程保持比例不变,步数是不变的),也是一个WA点。

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
long long x,y;
void extend_Eulid(long long a,long long b){
    if(b == 0){
        x = 1;y = 0;
    }else{
        extend_Eulid(b,a%b);
        long long temp = x;x = y;y = temp - a/b*y;
    }
}
long long gcd(long long a,long long b)
{
	if(a<b) swap(a,b);
	return b==0?a:gcd(b,a%b);
}
long long ans;
long long  k;
bool getLinerModualSolve(long long a,long long b,long long n)
{
    long long origin_b=b;
    
	long long tmp=gcd(a,b);
	if(n%tmp!=0) return false;
	a/=tmp;b/=tmp;n/=tmp;
	extend_Eulid(a,b);
	ans=x*n;
	ans=(ans%b+b)%b;
	return true;
}
int main()
{
	#ifndef ONLINE_JUDGE
		freopen("G:/1.txt","r",stdin);
		freopen("G:/2.txt","w",stdout);
	#endif
	long long A,B,C;
	while(cin>>A>>B>>C>>k)
	{
		if(!A&&!B&&!C&&!k)
			return 0;
        long long mod=(long long)1<<k;
		if(getLinerModualSolve(C,mod,B-A))
		{
			printf("%lld\n",ans);
		}
		else
		{
			printf("FOREVER\n");
		}
	}
	return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值