中国剩余定理 poj 2891 Strange Way to Express Integers

本文详细介绍了如何利用扩展欧几里得算法解决同余方程组的问题,包括基本原理、推广到一般情形的方法以及特殊情况下的处理策略。通过实例演示,展示了算法的应用过程,并提供了相关代码实现。最后,讨论了当方程组中模数不互质时的解法,以及如何将多个同余方程组合并求解。

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

 

对于同余方程组:

      x=a1 mod m1);   1

      x=a2 mod m2);    2

      方程组有一个小于mm1m2的最小公倍数)的非负整数解的充分必要条件是(a1-a2%m1m2==0 ,利用扩展欧几里德算法。

      两式联立:a1+m1*y=a2+m2*z

      则:a1-a2=m2*z-m1*y; 这样就可以了解出zy,则:x=a2+m2*z;  

      现在我们将其推广到一般情形:(设m1,m2,···,mk两两互素)

      x=a1mod m1;

     x=a2mod m2;

      ···

      x=akmod mk;其在M=m1*m2*···*mk;中有唯一整数解。

      记Mi=M/mi;因为(Mi,mi=1,故有两整数pi,qi满足Mi*pi+mi*qi=1,如果记ei=Mi*pi;那么:ei=0 mod mj,j!=i; ei=1mod mj,j=i;

      很明显,e1*a1+e2*a2+···+ek*ak就是方程的一个解,加减M倍后就可以得到最小非负整数解了。

   这种情况下 :


   a=B[1](mod W[1])   

   a=B[2](mod W[2])   

   ........   

   a=B[n](mod W[n])   

    

   W[i]W[j] 互质。 

   代码为:

 

int China(int B[],int W[],int k)   
   {      
       int i;   
       int d,x,y,a=0,m,n=1;   
       for(i=0;i<k;i++)   
       n*=W[i];   
       for(i=0;i<k;i++)   
       {
          m=n/W[i];   
          d=ext_euclid(W[i],m,x,y);   
          a=(a+y*m*B[i])%n;   
       }   
       if(a>0)
	   return a;   
       else
	   return(a+n);   
   } 


      如果m1,m2,···,mk不互素,那只能两个两个求了。

      x=a1 mod m1);  

      x=a2 mod m2);   

      解完后,a=x; m=m1m2的最小公倍数。即可


POJ 2891

Strange Way to Express Integers
Time Limit: 1000MS Memory Limit: 131072K
Total Submissions: 5072 Accepted: 1385

Description

Elina is reading a book written by Rujia Liu, which introduces a strange way to express non-negative integers. The way is described as following:

Choose k different positive integers a1a2…, ak. For some non-negative m, divide it by every ai (1 ≤ i ≤ k) to find the remainder ri. If a1a2, …, ak are properly chosen, m can be determined, then the pairs (airi) can be used to express m.

“It is easy to calculate the pairs from m, ” said Elina. “But how can I find m from the pairs?”

Since Elina is new to programming, this problem is too difficult for her. Can you help her?

Input

The input contains multiple test cases. Each test cases consists of some lines.

  • Line 1: Contains the integer k.
  • Lines 2 ~ k + 1: Each contains a pair of integers airi (1 ≤ i ≤ k).

Output

Output the non-negative integer m on a separate line for each test case. If there are multiple possible values, output the smallest one. If there are no possible values, output -1.

Sample Input

2
8 7
11 9

Sample Output

31

Hint

All integers in the input and the output are non-negative and can be represented by 64-bit integral types.


分析:

这道题 ai与aj不是互质的,所以只能两个两个的算:

    x= b1 (mod a1)

    x= b2 (mod a2)

  x= b1 + a1*x = b2 +a2*y 

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;

__int64 x,y;

__int64 extended_euclid(int s,int t)   //拓展欧拉函数
{
	__int64 i,temp;
	if(t==0)
	{
		x=1;
		y=0;
		return s;
	}
	else 
	{
		i=extended_euclid(t,s%t);
		temp=x;
		x=y;
		y=temp-(s/t*y);
		return i;
	}
}

int main()
{
	__int64 a1,a2,b1,b2,t,c,n,m,i,j;
	while(scanf("%I64d",&t)!=EOF)
	{
		scanf("%I64d%I64d",&a1,&b1);
		int ok=0;
		for(i=0;i<t-1;i++)
		{
			scanf("%I64d%I64d",&a2,&b2);
			if(ok) continue;
			int e=extended_euclid(a1,a2);
			c=b2-b1;
			if(c%e)
			{
				ok=1;
				continue;
			}
			int q=a2/e;
			x=(x*c/e%q+q)%q;      //求最下小的解。。
			b1=a1*x+b1;           // b=x;
			a1=a1*a2/e;           // a为a1和a2的最小公倍数。
		}
		if(ok) printf("-1\n");
		else printf("%lld\n",b1);
	}
	return 0;
}




   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值