对应每一组输入,在独立一行中输出一个正整数,表示满足条件的X的个数。
0 1 2 3 4 5 6 7 8 9
3
题意:求线性模方程组的解在给定闭区间内的个数;
思路:余数可能不互质 ,用CRT+EXGCD合并方程求出最小非负数解,再用二元一次方程讨论解得个数;
失误:二元一次方程求区间解的个数注意讨论,一般用排除法先排除不可能的情况,如果逐一讨论真的很麻烦,例如:[a,b] :a>0 ; b<0 ; b>0&&a<0 就这个清晰的情况就有三种情况,如果再加上a,b的大小不确定,开闭区间不确定的话就难受死了(这一·题就栽到这了),以后遇到二元一次求区间解的个数优先考虑排除;
AC代码:
#include<cstdio> int a[22],b[33],N; int Exgcd(int a,int b,int &x,int &y) { if(!b) { x=1;y=0; return a; } int r=Exgcd(b,a%b,y,x); y=y-(a/b)*x; return r; } int CRT(int a[],int m[], int n) { int mod=0,i=0,ans=0,a1=a[1],m1=m[1],a2,m2; for(i=2;i<=n;++i) { a2=a[i]; m2=m[i]; int c=a2-a1; int x=0,y=0; int d=Exgcd(m1,m2,x,y); if(c%d) return 0; x=c/d*x; mod=m2/d; x=(x%mod+mod)%mod; a1+=m1*x; m1*=mod; } if(N<a1) return 0;//此处处理上wa了好几次 如果最小非负解超出所要求范围则为0 ans=(N-a1)/m1+1;//[1,N]->[a1,N] a1是非负最小解 所以a1=0再判断 if(a1==0) ans--;//这种判断简单多了 return ans; } int main() { int T,i,M; scanf("%d",&T); while(T--) { scanf("%d %d",&N,&M); for(i=1;i<=M;++i) scanf("%d",&a[i]); for(i=1;i<=M;++i) scanf("%d",&b[i]); int ans=CRT(b,a,M); printf("%d\n",ans); } return 0; }