思路:解同余方程组,求出最小正整数解x0,然后解系就是x0+t*lcm(a0,a1,...an),求出其中满足要求的个数
错误:没有考虑到最小解释0的时候个数要减去1。
代码如下:
#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll;
ll a[20];
ll b[20];
ll extend_gcd(ll a,ll b,ll &x,ll &y)
{
if(b==0){
x=1;y=0;
return a;
}
else{
ll r=extend_gcd(b,a%b,y,x);
y-=x*(a/b);
return r;
}
}
int main(){
// freopen("data.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--){
ll n;
int m;
scanf("%I64d%d",&n,&m);
for(int i=0;i<m;++i){
scanf("%I64d",&a[i]);
}
for(int i=0;i<m;++i){
scanf("%I64d",&b[i]);
}
ll r1=b[0];
ll a1=a[0];
bool have=1;
for(int i=1;i<m;++i){
ll r2=b[i];
ll a2=a[i];
ll a=a1;
ll b=a2;
ll c=r2-r1;
ll x,y;
ll d=extend_gcd(a,b,x,y);
if(c%d){have=0;break;}
ll t=b/d;
ll x0=(x*(c/d)%t+t)%t;
r1=a1*x0+r1;
a1=a1*(a2/d);
}
if(!have||r1>n){printf("0\n");continue;}
ll ans=n-r1;
ans/=a1;
if(ans&&r1==0)ans--;
printf("%I64d\n",ans+1);
}
return 0;
}