【hdu 3579】Hello Kiki(数论--拓展欧几里德 求解同余方程组)
题意:Kiki 有 X 个硬币,已知 N 组这样的信息:X%x=Ai , X/x=Mi (x未知)。问满足这些条件的最小的硬币数,也就是最小的正整数 X。
解法:转化一下题意就是 拓展欧几里德求解同余方程组了。我们可以得到 N 个方程:Mi*x+Ai=X。一些解释请看下面的代码。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 using namespace std; 6 typedef long long LL; 7 8 LL aa[8],mm[8]; 9 10 LL mabs(LL x) {return x>0?x:-x;} 11 LL exgcd(LL a,LL b,LL& x,LL& y) 12 { 13 if (!b) {x=1,y=0; return a;} 14 LL d,tx,ty; 15 d=exgcd(b,a%b,tx,ty); 16 x=ty,y=tx-(a/b)*ty; 17 return d; 18 } 19 int main() 20 { 21 int T,n; 22 scanf("%d",&T); 23 for (int kase=1;kase<=T;kase++) 24 { 25 scanf("%d",&n); 26 for (int i=1;i<=n;i++) scanf("%I64d",&mm[i]); 27 for (int i=1;i<=n;i++) scanf("%I64d",&aa[i]); 28 LL a,m,d,x,y; 29 a=aa[1],m=mm[1]; 30 bool ok=false; 31 for (int i=2;i<=n;i++) 32 { 33 d=exgcd(m,mm[i],x,y);//mx-mm[i]y=aa[i]-a 34 if ((aa[i]-a)%d!=0) {ok=true;break;} 35 x=x*((aa[i]-a)/d); 36 LL t=mabs(mm[i]/d); 37 x=(x%t+t)%t; 38 a=m*x+a,m=m*mm[i]/d;//保证了x最小,a相应的也是最小的 39 } 40 LL ans; 41 if (ok) ans=-1; 42 else {ans=a; if (!ans) ans+=m;} 43 printf("Case %d: %I64d\n",kase,ans); 44 } 45 return 0; 46 }