题目链接: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();
}
}