poj 2115 C Looooops 拓展欧几里德 解模线性方程模板

题意:求for (variable = A; variable != B; variable += C)的循环次数,其中变量为k比特无符号整数。


求解形如 ax=b(mod n)的方程,对于整数x来说,方程要么无解,无数个解。

如果表示成对应等价类[a]n *[x]n = [x*b]nx[0,n-1]。([a]n代表x%n=a.的所有满足条件的x所组成的集合,其中a为集合中最小非负整数,用最小的非负整数来代表整个集合,即[a]n={a+k*n,kZ)})

对于集合来说只有一个解[x0]n.

无数个解无意义,一般讨论在0~n-1上有多少解。

ax=b(mod n)=> ax+ny=b

如果b不是d=gcd(a,n)的倍数,方程无解

否则在0~n-1上有d个解,任意两个解与n/d同余(x0=x+k*(n/d))


 

题目中:解出的x0不一定是最小非负的,将其转化成最小非负解即是答案

思路: (a + c*x)% 2^k = b;  cx = b-a   (mod 2^k) ,=>  cx + 2^k*y=(b-a)求解模线性方程,x取最小正整数解

#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
void exgcd(ll a,ll b,ll &d,ll &x,ll &y)
{
	if(!b)
	{
		d=a;
		x=1;y=0;
	}
	else
	{
		exgcd(b,a%b,d,y,x);
		y-=x*(a/b);
	}
}
int main()
{
	ll A,B,C,k;
//	freopen("in.txt","r",stdin);
	while(~scanf("%I64d%I64d%I64d%I64d",&A,&B,&C,&k))
	{
		if(A+B+C+k==0)break;
		ll b=(ll)1<<k; // k位的最大数字是(1<<k)-1 但是这里是取1<<k 
		ll a=C;
		ll c=B-A;
		ll d,x,y;
		exgcd(a,b,d,x,y);
		if(c%d)
		{
			printf("FOREVER\n");
		}
		else
		{
			x*=(c/d);
			ll t=b/d;
			if(t<0)t=-t;
			x=(x%t+t)%t;
			printf("%I64d\n",x);
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值