HDUOJ-----X问题

X问题

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

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
 
Author
lwg
 
Source
中国剩余定理,与欧几里得扩展结合.......
 
 1 #include<iostream>

 2 #define LL long long

 3 #include<cstdio>

 4 using namespace std;

 5 

 6 LL x,y,q;

 7 LL gcd(LL a,LL b)

 8 {

 9     if(b!=0)

10     return    gcd(b,a%b);

11     else

12        return a;

13 }

14 void exgcd(LL a,LL b)

15 {

16   if(b==0)

17         x=1 , y=0 , q=a;

18   else

19   {

20    exgcd(b,a%b);

21    LL temp=x;

22      x=y,y=temp-a/b*y;

23   }

24 }

25 

26 int main()

27 {

28  int test,m,i;

29  int n,a[12],r[12];

30  LL lcm;

31  bool ifhave; 

32  scanf("%d",&test);

33  while(test--)

34  {

35   scanf("%d%d",&n,&m);

36   lcm=1;

37   ifhave=true;

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

39   {

40     scanf("%d",a+i);

41     lcm=lcm/gcd(lcm,a[i])*a[i];  //求最小公倍数

42   }

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

44       scanf("%d",r+i);

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

46   {

47     exgcd(a[0],a[i]);

48     if((r[i]-r[0])%q)

49     {

50        ifhave=false;   //不需要在判断了

51        break;

52     }

53     LL t=a[i]/q;

54    x=((x*(r[i]-r[0])/q)%t+t)%t;

55    r[0]+=a[0]*x;

56    a[0]*=(a[i]/q);

57  }

58   if(!ifhave)

59   {

60       printf("0\n");

61   }

62   else

63   {

64       LL ans=0;

65       if(r[0]<=n)

66           ans=1+(n-r[0])/lcm;

67       if(ans&&r[0]==0)

68           ans--;

69       printf("%I64d\n",ans);

70   }

71  }

72  return 0;

73 }
代码复制

 

 

你可能感兴趣的:(HDU)