题目链接:USACO - Fractions to Decimals
之前做过小数化分数的题:
这次是分数
a/b
化小数。
首先我们可以处理出整数部分
a/b
。
考虑到小学算除法的方法“长除法”。我们可以发现,当算到某一步时,这个余数在之前出现过,那么说明找到了循环节。
如:
41/333=0......41
410/333=1......77
770/333=2......104
1040/333=3......41
这里就发现余数41已经出现过了。那么下一步的答案肯定是1。
说明找到了循环节(123)。
/*
ID: xdujlx1
PROG: fracdec
LANG: C++
*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int vis[100007];
int xs[100007];
int n=0;
void ioinit()
{
freopen("fracdec.in","r",stdin);
freopen("fracdec.out","w",stdout);
}
int main()
{
//ioinit();
int a,b;
cin>>a>>b;
int zs=a/b;
a-=a/b*b;
int st=-1;
memset(vis,-1,sizeof(vis));
if(a%b!=0)
for(n=0;;n++)
{
if(a==0) break;
if(vis[a]!=-1)
{
st=vis[a];
break;
}
vis[a]=n;
a*=10;
xs[n]=a/b;
a-=a/b*b;
}
string ans;
if(n==0) printf("%d.0\n",zs);
else
{
stack<int> sta;
while(1)
{
sta.push(zs%10+'0');
zs/=10;
if(zs==0) break;
}
while(!sta.empty())
{
ans.push_back(sta.top());
sta.pop();
}
ans.push_back('.');
for(int i=0;i<n;i++)
{
if(i==st) ans.push_back('(');
ans.push_back(xs[i]+'0');
}
if(st!=-1) ans.push_back(')');
}
for(int i=0;i<ans.size();i+=76)
{
for(int j=i;j<ans.size()&&j-i<76;j++)
cout<<ans[j];
cout<<endl;
}
return 0;
}