poj2891 Strange Way to Express Integers 解线性同余方程的应用

这是以前做过的一道题目,只不过那时候瞎来,看了别人的题解是另一种方法,这次纯自己做出的,就是简单的解线性同余方程

不打解析过程了,只打一个解线性同余方程的方法,自己以后回顾这道题目的时候可以看看思考做:


x≡b1(mod m1)

x≡b2(mod m2)

令m=[m1,m2]

首先此方程有解的充分必要条件是 (m1,m2) | (b1-b2),此时方程仅有一个小于0的非负整数解,

式子1:等价于  x=b1+m1y1;

式子2:等价于  x=b2+m2y2;

联立可得 b1+m1y1=b2+m2y2,移项 m2y2-m1y1=b1-b2,一看就是用扩展欧几里德来解决了


给例子

x≡r1(mod a1)

x≡r2(mod a2)

x≡r3(mod a3)

.

.

.

x≡rn(mod an);

bool flag=false;
		scanf("%I64d %I64d",&a1,&r1);
		for(int i=1;i<n;i++)
		{
			scanf("%I64d %I64d",&a2,&r2);
			LL a=a1,b=a2,c=r2-r1;
			LL x0,y0;
			LL gcd=exgcd(a,x0,b,y0);
			if(c%gcd!=0)
				flag=true;
			LL MOD=b/gcd;
			x0=((x0*c/gcd)%MOD+MOD)%MOD;
			r1=a1*x0+r1;
			a1*=(a2/gcd);
		}
		if(flag)
			puts("-1");
		else
			printf("%I64d\n",r1);


接下来本题代码

#include<iostream>
#include<cstdio>
#include<list>
#include<algorithm>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<cmath>
#include<memory.h>
#include<set>

#define ll long long
#define LL __int64
#define eps 1e-8
#define e 2.718281828

//const ll INF=9999999999999;

#define M 400000100

#define inf 0xfffffff

using namespace std;

//vector<pair<int,int> > G;
//typedef pair<int,int> P;
//vector<pair<int,int>> ::iterator iter;
//
//map<ll,int>mp;
//map<ll,int>::iterator p;
//
//vector<int>G[30012];

LL exgcd(LL a,LL &x,LL b,LL &y)
{
	if(b==0)
	{
		x=1;
		y=0;
		return a;
	}
	LL r=exgcd(b,x,a%b,y);
	LL tmp=x;
	x=y;
	y=tmp-a/b*y;
	return r;
}


int main(void)
{
	int t;
	LL a1,r1,a2,r2;
	while(cin>>t)
	{
		bool flag=false;
		scanf("%I64d %I64d",&a1,&r1);
		for(int i=1;i<t;i++)
		{
			scanf("%I64d %I64d",&a2,&r2);
			LL a=a1,b=a2,c=r2-r1;
			LL x0,y0;
			LL gcd=exgcd(a,x0,b,y0);
			if(c%gcd!=0)
				flag=true;
			LL MOD=b/gcd;
			x0=((x0*c/gcd)%MOD+MOD)%MOD;
			r1=a1*x0+r1;
			a1*=(a2/gcd);
		}
		if(flag)
			puts("-1");
		else
			printf("%I64d\n",r1);
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值