HDU 1573 X问题 数论-(中国剩余定理)

题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=1573


求中国剩余定理解的个数

注意是非互质情况下的中国剩余定理

 

N===a1(mod r1)

N===a2(mod r2)

以两个为例,则N=a1+r1*x=a2+r2*y,根据后两者就可以建立方程  r1*x-r2*y=a2-a1,扩展欧几里德可搞。

解出x之后 可知N=a1+r1*x,明显这是其中一组解,N+K*(r1*r2)/gcd都是解。


代码如下:

 

#include <iostream>

#include <cstdio>

#include <cstdlib>

#include <cmath>

#include <cstring>

#include <string>

#include <algorithm>

#include <vector>

#include <set>

#include <map>

#include <queue>

using namespace std;



/*

freopen("input.txt",  "r", stdin);  //读数据

freopen("output.txt", "w", stdout); //注释掉此句则输出到控制台

*/

int n,m,b[15],w[15];

//扩展Euclid求解gcd(a,b)=ax+by

int ext_gcd(int a,int b,int& x,int& y)

{

    int t,ret;

    if (!b)

    {

        x=1,y=0;

        return a;

    }

    ret=ext_gcd(b,a%b,x,y);

    t=x,x=y,y=t-a/b*y;

    return ret;

}



void China_left()

{

    int flag,w1,w2,b1,b2,gcd,x,y,i,t;

    flag=0;w1=w[0];b1=b[0];

    for(i=1;i<m;i++)

    {

        w2=w[i];b2=b[i];

        gcd=ext_gcd(w1,w2,x,y);

        if((b2-b1)%gcd)

        {

            flag=1;break;

        }

        t=w2/gcd;

        x=(x*(b2-b1))/gcd;

        x=(x%t+t)%t;

        b1=w1*x+b1;

        w1=(w1*w2)/gcd;

        b1=(b1%w1+w1)%w1;

    }

    if(flag||n<b1)

        printf("0\n");

    else

        printf("%d\n",(n-b1)/w1+1-(b1==0?1:0));

}



int main()

{

    int i,j,k,tt;

    cin>>tt;

    while(tt--)

    {

        cin>>n>>m;

        for(i=0;i<m;i++)

            scanf("%d",&w[i]);

        for(i=0;i<m;i++)

            scanf("%d",&b[i]);



        China_left();

    }

    return 0;

}


 


你可能感兴趣的:(HDU)