HDU 1713 gcd应用
思路:
分数的“最小公倍数”
以例子来说: 26501/6335 18468/42
其实这两个值就是 每圈需要多少天; 如果两个数 / 之后得到的结果是整数就好办了;
就是求他们的最小公倍数;
但是,其实分数也能求最小公倍数:
根据欧几里德定理: gcd(k*a,k*b) = k*gcd(a,b); so....gcd(a,b) = gcd(k*a,k*b)/k;
我们来设置几个变量,a1,a2,b1,b2;
分别代表第一个数的分子分母 和第二个数的。。。
设d 为最小公倍数: d = gcd(a1/a2 , b1/b2)
= gcd(a1,b1*a2/b2) / a2
= gcd(a1*b2 , b1*a2) / (a2*b2);
他们的最大公约数:q = (a1/a2)*(b1/b2)/( gcd(a1*b2,a2*b1) / (a2*b2) );
最后对分数处理下,使得其最简; 另注意 类型用 __int64。gcd()函数的参数也要同步用__int64
#include <iostream> using namespace std; int gcd(__int64 a, __int64 b) //欧几里德 算法 { return b?gcd(b,a%b):a; } int main() { int t; __int64 a1,a2,b1,b2; scanf("%d",&t); while(t--) { scanf("%I64d/%I64d %I64d/%I64d",&a1,&a2,&b1,&b2); __int64 ans1 = a1*b1, ans2 = gcd(a1*b2,a2*b1); __int64 d = gcd(ans1,ans2); printf("%I64d",ans1/d); if((ans2/d) != 1) printf("/%I64d\n",ans2/d); else printf("\n"); } }
HDU 1717
对于非循环小数好办;关键是循环小数;
每个循环小数都可以化为分数形式;
0.X(Y) 假定x位数为n,Y的位数为m;
则 分数的分子 fz = X*n+Y-X;
fm = 99...9*10^n (m个9);
X为0,则n为0
#include <iostream> #include <string> using namespace std; int gcd(int a, int b) { return b?gcd(b,a%b):a; } int main() { int t; char c[50]; cin>>t; cin.get(); while(t--) { cin>>c; int p = 0,pnum = 0,fz = 0,fm = 0; //非循环书,非循环位数,分子,分母 int i = 2; while(c[i] != '('&&c[i]!='\0') // ( 左边 { p = p*10 + c[i++] - '0'; pnum++; } if(i==strlen(c)) { fz = p; fm = 1; } else { fz = p; i++; while(c[i] != ')'&&c[i]!='\0') //()之间的数 { fz = fz*10 + c[i++] - '0'; fm = fm * 10 + 9; } fz = fz - p; } while(pnum--) { fm *= 10; } int d = gcd(fz,fm); fz /= d; fm /= d; cout<<fz<<"/"<<fm<<endl; } }