hdu3579 Hello Kiki(数论)

用到中国剩余定理,然后用扩展欧几里得算法求解。

这里有两个注意点,1、硬币数量不能为0或者负数

                                   2、每个group数量有可能大于50,样例中就有

 

#include<stdio.h>
#include<math.h>
#include<stdlib.h>
int M[10],A[10],n;
int extEuclid(int p,int q,int &x,int &y)//扩展欧几里得算法
{
	int d,tmp;
	if(q==0){x=1;y=0;return p;}
	d=extEuclid(q,p%q,x,y);
	tmp=x;x=y;y=tmp-p/q*y;
	return d;//返回最大公约数
}
int calcu(int cur)
{
    int x,y,g,t;
    int a1=M[cur-1],a2=M[cur];
    int b1=A[cur-1],b2=A[cur];
    g=extEuclid(a1,a2,x,y);
    int s=b2-b1;
    if(s%g)
       return -1;
    else
    {	
    	t=a2/g;
    	x=x*s/g;//这个一定要放在“x=(x%t+t)%t”前面,否则就wa了
        x=(x%t+t)%t;//求出在0~t之间的一个解。这一步必须有,否则就wa,因为爆int了,可改成long long,改过后也可以ac
    	a2=a1*a2/g;
    	s=((a1*x+b1)%a2+a2)%a2;
	    A[cur]=s;
	    M[cur]=a2;
        if(cur==n-1)
        {
           if(s==0)
    	      return M[cur];
    	   else
    	      return A[cur];
        }
 		else
    	  return calcu(cur+1);
    }
}
int main()
{
	int i,j,k,t;
	scanf("%d",&t);
	for(k=1;k<=t;k++)
	{
		scanf("%d",&n);
		for(i=0;i<n;i++)
		  scanf("%d",&M[i]);
        for(i=0;i<n;i++)
          scanf("%d",&A[i]);
        printf("Case %d: ",k);
        if(n==1)
        {
        	if(A[0]==0)
        	  A[0]=M[0];
        	printf("%d\n",A[0]);
        	continue;
        }
         printf("%d\n",calcu(1));
	}
	return 0;
}


 


 

你可能感兴趣的:(HDU)