中国的剩余定理。
思路是:先求w数组里面的最小公倍数lcm。方程在小于N的范围的解是a,则a+lcm*x<=N,其中x就是解的个数。
AC代码:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
__int64 gcd(__int64 a,__int64 b)
{
return b==0?a:gcd(b,a%b);
}
void exgcd(__int64 a,__int64 b,__int64 &d,__int64 &x,__int64 &y)
{
if(b == 0)
{
x=1;y=0;
d=a;
return ;
}
else
{
exgcd(b,a%b,d,y,x);
y -= x*(a/b);
}
}
int main()
{
__int64 ans,e,n,m,a,b,c,d,x,y,lcm;
__int64 q[13],w[13];
int t,ant,i;
scanf("%d",&t);
while(t--)
{
cin>>n>>m;
ant=1;
lcm=1;
for(i=1;i<=m;i++)
{
cin>>q[i];
lcm=lcm/gcd(lcm,q[i])*q[i];
}
for(i=1;i<=m;i++)
{
cin>>w[i];
}
for(i=2;i<=m;i++)
{
a=q[1];
b=q[i];
c=w[i]-w[1];
exgcd(a,b,d,x,y);
if(c%d != 0)
{
ant=0;break;
}
e=b/d;
x=(x*(c/d)%e+e)%e;
w[1]=q[1]*x+w[1];
q[1]=q[1]*(q[i]/d);
}
if(ant == 0)
{
printf("0\n"); continue;
}
ans=0;
if(w[1]<=n) ans=1+(n-w[1])/lcm;
if(ans && w[1]==0) ans--;
cout<<ans<<endl;
}
return 0;
}
路途中。。。。