###题目:
POJ -1930 Dead Fraction(GCD+循环小数化分数)
###题意:
给你一个循环小数,小数后有一部分省略,求小数转换为分数后的分母最小的分数。
###题解:
1.首先枚举循环节长的a(0 < a <= len-5) ,len = size(),循环节为s.substr(len-3-a,a);
2.然后由后向前匹配循环节,找到循环节第一次出现的位置首端st,求得循环节首端到小数点的距离c = st - 2;
3.然后由公式(10(a+c)x+10c求得分子分母(无限循环小数化分数解析),利用GCD求的分子分母最小公因数进行约分。
4.求得由不同循环节所得到的分数,取分母最小的输出即可。
###AC代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <string>
typedef long long LL;
using namespace std;
LL ansx,ansy;
LL GCD(LL a,LL b)
{
if(b==0)
return a;
else return GCD(b,a%b);
}
string s;
void fun(int a,int c)
{
LL x=0,y=0,r=1,q=1;
for(int i = 2; i < 2+c+a; i++)
y = y*10 + (s[i]-'0');
for(int i = 2; i < 2+c; i++)
x = x*10 + (s[i]-'0');
for(int i = 0; i < a+c; i++)
r *= 10;
for(int i = 0; i < c; i++)
q *= 10;
LL z = GCD((y-x),r-q);
if((r-q)/z < ansy)
{
// cout << a << " " << c << " " << x << " " << y << " " << z << " " << r << " " << q << " " << endl;
ansx = (y-x)/z;
ansy = (r-q)/z;
// cout << ansx << " "<< ansy << endl;
}
}
int main()
{
while(cin >> s && s.size() != 1)
{
ansy = 1000000000000000000;
int len = s.size();
int ma = len - 5;//可枚举的长度
int a;//循环节长度
int c;//循环节首到小数点的距离
for(a = 1; a <= ma; a++)
{
int st = len - 3 - a;
string ss =s.substr(st,a);
st -= a;
while(st >= 2&&ss==s.substr(st,a)) st -= a;
c = (st+a) - 2;
fun(a,c);
}
printf("%lld/%lld\n",ansx,ansy);
}
return 0;
}