X问题
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2461 Accepted Submission(s): 755
Problem Description
求在小于等于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)。
Input
输入数据的第一行为一个正整数T,表示有T组测试数据。每组测试数据的第一行为两个正整数N,M (0 < N <= 1000,000,000 , 0 < M <= 10),表示X小于等于N,数组a和b中各有M个元素。接下来两行,每行各有M个正整数,分别为a和b中的元素。
Output
对应每一组输入,在独立一行中输出一个正整数,表示满足条件的X的个数。
Sample Input
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
Sample Output
1 0 3 判断同余方程组在某个范围内解得个数的问题 在poj2891(同余方程组最小正整数解)的基础上增加一个不等式的过程:令a数组中所有数的最小公倍数为lcm,方程在lcm范围内的非负整数解释a,则有a+lcm*x<=N; 若a!=0,那么解得x就是解的个数,否则x-1即为解的个数;#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; ll gcd(ll a,ll b) { if(b==0) return a; else return gcd(b,a%b); } void exgcd(ll a,ll b,ll &d,ll &x,ll &y) { if(b==0) {d=a;x=1;y=0;} else { exgcd(b,a%b,d,y,x); y-=x*(a/b); } } int main() { int i,T,aa[20],rr[20]; scanf("%d",&T); while(T--) { int n,m; ll lcm=1; ll x0,y0,d; bool ifhave=true; scanf("%d%d",&n,&m); for(i=1;i<=m;i++) { scanf("%d",&aa[i]); lcm=lcm/gcd(lcm,aa[i])*aa[i]; } for(i=1;i<=m;i++) scanf("%d",&rr[i]); for(i=2;i<=m;i++) { ll a=aa[1],b=aa[i],c=rr[i]-rr[1]; exgcd(a,b,d,x0,y0); if(c%d!=0) { ifhave=false; continue; } ll t=b/d; x0=(x0*(c/d)%t+t)%t; rr[1]=aa[1]*x0+rr[1]; aa[1]=aa[1]*(aa[i]/d); } ll ans=0; if(rr[1]<=n) { ans=1+(n-rr[1])/lcm; } if(ans&&rr[1]==0) ans--; if(!ifhave) printf("0\n"); else printf("%lld\n",ans); } return 0; }