HDU 1573 X问题(中国剩余定理标准解法)

X问题

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 8354    Accepted Submission(s): 3031

 

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

扫描二维码关注公众号,回复: 4588437 查看本文章

linle   |   We have carefully selected several similar problems for you:  1788 1695 1452 1060 1299 

中国剩余定理(a[i]不一定互质的情况):
	ans%a1=r1,ans%a2=r2,求最小的ans;
	解方程a1*x1+r1=a2*x2+r2;
	则a1*x1-a2*y1=r2-r1;
	利用拓展欧几里得解a1*x2-a2*y2=d;
	得出d=gcd(a1,a2);
	只有(r2-r1)%d=0时方程有解
	从而得出x1=x2*(r2-r1)/d,y1=y2*(r2-r1)/d;
	p=a2/d;
	a1*x1+a2*y1=r2-r1;
	a1*(x1+a2/d)-a2*(y1-a1/d)=r2-r1;
	x1=(x1*(r2-r1)%p+p)%p;//使x为最小的正整数解
	最终ans=a1*x1+r1;
#include<iostream>
#define ll long long
using namespace std;
ll a[13],b[13];
void exgcd(ll m,ll n,ll &gcd,ll &x,ll &y){
        if(!n){
                gcd=m;//printf("gcd=%lld\n",gcd);
                x=1,y=0;
        }else{
                exgcd(n,m%n,gcd,x,y);
                ll tmp=x;
                x=y;
                y=tmp-(m/n)*y;
        }
}
int main()
{
        int T;
        scanf("%d",&T);
        while(T--){
                ll maxn,n;
                scanf("%lld%lld",&maxn,&n);
                for(int i=0;i<n;i++)
                        scanf("%lld",&a[i]);
                for(int i=0;i<n;i++)
                        scanf("%lld",&b[i]);
                bool flag=0;
                ll a1=a[0],b1=b[0];
                for(int i=1;i<n;i++)
                {
                        ll x,y,gcd,a2=a[i],b2=b[i];
                        exgcd(a1,a2,gcd,x,y);
                        if((b2-b1)%gcd){
                                flag=1;break;
                        }
                        ll k=(b2-b1)/gcd,p=a2/gcd;
                        x=(x*k%p+p)%p;//使x为最小的正整数解
                        b1=a1*x+b1;
                        a1=a1/gcd*a2;
                }
                if(flag||b1>maxn){
                        printf("0\n");
                }else{
                        int ans=b1?1:0;//b1=0时b1不能作为解
                        while(b1+a1<=maxn)
                                b1+=a1,ans++;
                        printf("%d\n",ans);
                }
        }
        return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_42060896/article/details/85140544