版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/winter2121/article/details/81975927
问题 T: 【数论】X问题
时间限制: 1 Sec 内存限制: 128 MB
提交: 5 解决: 3
[提交] [状态] [讨论版] [命题人:admin]
题目描述
求在小于等于N的正整数中有多少个X满足:X mod a[0] = b[0], X mod a[1] = b[1], X mod a[2] = b[2], …, X mod a[i] = b[i], … (0 < a[i] <= 10)。
输入
输入数据的第一行为一个正整数T,表示有T组测试数据。每组测试数据的第一行为两个正整数N,M (0 < N <= 1000,000,000 , 0 < M <= 10),表示X小于等于N,数组a和b中各有M个元素。接下来两行,每行各有M个正整数,分别为a和b中的元素。
输出
对应每一组输入,在独立一行中输出一个正整数,表示满足条件的X的个数。
样例输入
3 10 3 1 2 3 0 1 2 100 7 3 4 5 6 7 8 9 1 2 3 4 5 6 7 10000 10 1 2 3 4 5 6 7 8 9 10 0 1 2 3 4 5 6 7 8 9
样例输出
1 0 3
【分析】
根据题意,很明显的线性同余方程组。
结合拓展欧几里得可以解得最小特解px,然后分情况计算一下n之内的特解个数即可。
线性同余方程:https://blog.csdn.net/winter2121/article/details/71123565
【代码】
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b){while(b)b^=a^=b^=a%=b;return a;}
int exgcd(int a,int b,int &x,int &y)
{
if(b==0)
{
x=1; y=0; return a;
}
int d=exgcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
int getpx(int x[],int y[],int top)
{
int a=x[0],b=y[0],k1,k2;
for(int i=1;i<top;i++)
{
int r=y[i]-b;
int d=exgcd(a,x[i],k1,k2);
ll lcm=1ll*a/d*x[i];
if(r%d)return -1; //无解
int t=x[i]/d;
k1=(k1*r/d%t+t)%t;
b=k1*a+b;
a=lcm;
b%=a;
}
return b;
}
int solve()
{
int n,m,a[12],b[12];
int x[12],y[12];
scanf("%d%d",&n,&m);
ll lcm=1;
for(int i=0;i<m;i++)scanf("%d",&a[i]),lcm=lcm*a[i]/gcd(lcm,a[i]);
for(int i=0;i<m;i++)scanf("%d",&b[i]);
ll px=getpx(a,b,m);
ll ans=0;
if(px==0)ans=n/lcm;
else if(px==-1)ans=0;
else if(n>=px)ans=(n-px)/lcm+1;
else ans=0;
printf("%lld\n",ans);
}
int main()
{
int T;
for(cin>>T;T--;)solve();
}