hdu 1573 中国剩余定理

本文详细介绍了使用中国剩余定理解决一类特定的数学问题——寻找满足多个同余条件的正整数。通过实例讲解了扩展欧几里德算法的应用,并提供了一段完整的C++实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://blog.youkuaiyun.com/u013050857/article/details/48573257

【题目大意】:求在小于等于N的正整数中有多少个X满足:X mod a[0] = b[0], X mod a[1] = b[1], X mod a[2] = b[2], …, X mod a[i] = b[i], … (0 < a[i] <= 10)。

#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define INF 99999999
#define uf 1e-8 
#define maxn 1000005
#define LL long long
using namespace std;
int a[11],b[11];
int N,m;
LL extgcd(LL a,LL b,LL &x,LL &y)
{
	if(b==0)
	{
		x=1;
		y=0;
		return a;
	}
	else
	{
		LL d=extgcd(b,a%b,x,y);
		LL t=x;
		x=y;
		y=t-(a/b)*y;
		return d;
	}
}
void solve()// a*x+b*y=gcd(a,b)=d;(x,y) 为其一组整数解 
{
	LL x,y,d,m1,r1,m2,r2;
	m1=a[0];
	r1=b[0];
	int flag=0;
	for(int i=1;i<m;i++)
	{
		m2=a[i];
		r2=b[i];
		d=extgcd(m1,m2,x,y);
		LL c=r2-r1;
		if(c%d!=0)
		{
			flag=1;
			break;
		}
		LL t=m2/d;
		x=c/d*x; 
		x=(x%t+t)%t;
		r1=m1*x+r1;//两者符合条件的N 
		m1=m1*m2/d; //m1和m2的最大公倍数 
	}
	if(flag||N<r1)
	{
		puts("0");
	}
	else
	{
		LL ans=(N-r1)/m1+1;//m1*x+r1==N均符合 
		if(r1==0)//如果余数为0 
			ans--;
		printf("%lld\n",ans);
	}
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d %d",&N,&m);
		for(int i=0;i<m;i++)
			scanf("%d",&a[i]);
		for(int i=0;i<m;i++)
			scanf("%d",&b[i]);
		solve();	
	}
	return 0;	
} 

中国剩余定理—详解

定理描述:

  中国剩余定理:求解同余式组的方法。

  例如下面的一元线性同余方程组:

  x ≡ a1 (mod m1)

  x ≡ a2 (mod m2)

  x ≡ a3 (mod m3)

    . . . . . . 

  x ≡ an (mod mn)      

  中国剩余定理:假设整数m1, m2, m3......, mn两两互质,则对于任意的整数a1, a2, a3...., x有解。

 

解决问题类型:

  在<孙子算经>里有一个问题: 有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二。问物几何?

 

计算及推导

  他的计算过程是:

            70是能被5和7整除的数字,除以3正好余1。

              21是能被3和7整除的数字,除以5正好余1。

            15是能被3和5整除的数字,除以7正好余1。

  最后结果就为:( 70*2 + 21*3 + 15*2 ) % LCM(3, 5, 7) == 23

  就是说对于上面一元组的3个方程要逐级满足,相加之后并不会影响求余的结果,然后modLCM(3, 5,7)就是最小的答案。

  先满足第一个一元组 x ≡ 2 (mod 3) ,70能被5和7整除,除以3余1,然后乘上2后得到N1,N1就满足了一元组中的第一个式子。依次类推,对一元组中的每个式子都求出Ni,然后相加所得的X就是最终答案(因为Ni可以整除集合a中的所有元素,除ai之外,故对于第i个一元组来说,X加上Nj (j!=i), 并不会对mod ai有影响)。

 

  那么再看开始时候提到的一元线性同余方程:(先做几个设定:设Ni为能够被m1, m2,......, mi-1, mi+1, .....mn整除,但是除以mi正好余1)

    X = N1*a1 + N2*a2 + ....... + Nn*an就是我们要求的一个解,解集为X mod LCM(m1, m2, ...., mn)。

 

  剩下的问题就变成了如何求解N1, N2, ......, Nn,我们继续向下看:

    假设m = LCM(m1, m2, ......, mn), x', y'为任意整数。

    因为Ni的性质,Ni可以表示为:Ni == m / mi * x' == mi * y' + 1 ==> m / mi * x' + (-mi) * y' == 1.

  推到现在有没有感觉很熟悉,对的!这个就是扩展欧几里德:对于gcd(a, b) = d, 存在a*x+b*y == gcd(a, b)

      存在gcd(-mi, m/mi) == 1, 对于m / mi * x' + (-mi) * y' == 1, 套用一下扩展欧几里德求出x', 就可以求解出Ni。有了Ni就出X就是分分钟的事情辣!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值