X问题 - hdu1573 - 中国剩余定理

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1573

思路:

就是用中国剩余定理啦,再加一点变化。

题中让求的是小于等于N的x的个数,并且要是正整数。

我们用中国剩余定理把方程组:

x%m1=a1

x%m2=a2

……

x%mn=an

合并成一个方程

x%m=a,即x=a(mod m)

我们解得的a是最小值,m*i+a都是满足的值

所以答案是:(N-a)/m+1(+1是因为i能等于0)

若a==0那么ans--;(题中要求是正整数)

代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
#define ll long long
const int N=15;
int n,p,m[N],a[N];

ll extgcd(ll a,ll b,ll &x,ll &y){
	int d=a;
	if(b!=0){
		d=extgcd(b,a%b,y,x);
		y-=(a/b)*x;
	}
	else {x=1;y=0;}
	return d;
}

void work(){
	ll M=m[1],A=a[1],t,d,x,y;
	for(int i=2;i<=p;i++){
		d=extgcd(M,m[i],x,y);
		if((a[i]-A)%d){printf("0\n");return ;}
		x*=(a[i]-A)/d;t=m[i]/d;x=(x%t+t)%t;
		A=M*x+A,M=M*m[i]/d;A%=M;
	}
	A=(A%M+M)%M;
	if(A>n){printf("0\n");return ;}
	int ans=(n-A)/M+1;
	if(A==0)ans--;
	printf("%lld\n",ans); 
}

int main(){
	int t;
	scanf("%d",&t);
    while(t--){
    	scanf("%d%d",&n,&p);
    	for(int i=1;i<=p;i++){
    		scanf("%d",&m[i]);
		}
		for(int i=1;i<=p;i++){
    		scanf("%d",&a[i]);
		}
		work();
	}
}

猜你喜欢

转载自blog.csdn.net/m0_37579232/article/details/82113562