HDU 1573 X问题

该题是一道中国剩余定理题目,刚开始我就用了一下暴力的方法 (同时也优化了一下)一下子就超时了,后来看了一下这个题的解题报告才知道要用中国剩余定理,这也是我第一次用中国剩余定理解题。

这个定理又叫孙子定理。

就是给定几个数  虽然不互质   然后一个数取余他们又有相应的余数。那么这个问题的答案相差的一定是这些数的最小公倍数。

首先我们求出最小公倍数K;

然后在N%k+1到N%k+k这个范围内暴找一下有没有一个符合所有条件的数,我们把N分成一段段的,因为在每一段一定是没有或者只有一个的。为什么可以分成一段段的,我们知道中国剩余定理求的是最小的数,那么它的倍数同样是符合条件的;

所以如果有的话  sum+=n/k;

不要忘记,然后判断在1到n%k这个范围内有没有符合条件的答案 ( 因为我们是从数的最后面分段开始的,最前面可能还有数剩余 )。

#include<stdio.h>
#include
<stdlib.h>
int Gcd( int a, int b )
{
b
==0?a:Gcd( b, a%b );
}
int judge( int a[], int b[], int n, int sum, int N )
{
int count=0;
int t=N%sum;
for( int i=t+1;i<=sum+t;i++ )
{
int cnt=0;
for( int j=0; j<n; j++ )
{
if( i%a[j]==b[j] )
cnt
++;
else break;
}
if( cnt==n )
{
count
+=N/sum;
break;
}
}
for( int i=1;i<=t; i++ )
{
int cnt=0;
for( int j=0; j<n; j++ )
{
if( i%a[j]==b[j] )
cnt
++;
else break;
}
if( cnt==n )
{
count
++;
break;
}
}
return count;
}
int main( )
{
int a[10],b[10];
int n,T,N;
scanf(
"%d",&T );
while( T-- )
{
int sum=1;
scanf(
"%d%d",&N, &n );
for( int i=0; i<n; i++ )
{
scanf(
"%d",&a[i] );
int t=Gcd( sum , a[ i ] );
sum
*=(a[i]/t);
}
for( int i=0; i<n; i++ )
scanf(
"%d",&b[i] );
printf(
"%d\n",judge( a,b,n,sum,N ) );
}
return 0;    
}

  

posted @ 2011-08-19 16:39  wutaoKeen  阅读(1183)  评论(0编辑  收藏  举报