USACO section2.4 Fractions to Decimals题解&代码

这道模拟倒是出乎意料地顺利…
只是大错不犯小错不断…比如忘记76位换行啊…比如前导零忘记算进位数里啊…
恩总之交了3次才A掉…
关于loop的小技巧就是将原分数化简后分母的因子中5的个数与2的个数的较大值为小数部分的非循环位数,这样只要在计算循环部分时遇到余数相同的情况就可以直接结束了

/*
ID:rainbow16
LANG:C++
TASK:fracdec
*/
#include<iostream>
#include<stdio.h>
using namespace std;
int z,n,d,w,ans[100000],l=1,loop[100000],ll=0,c=0;
int gcd(int a,int b)
{
    if(!a)
        return b;
    return gcd(b%a,a);
}
int len(int a)
{
    int r=0,t=0;
    int x=a;
    while(x%2==0)
        x/=2,t++;
    if(t>r)
        r=t;
    t=0;
    while(x%5==0)
        x/=5,t++;
    if(t>r)
        r=t;
    return r;
}
int main(void)
{
    freopen("fracdec.in","r",stdin);
    freopen("fracdec.out","w",stdout);
    scanf("%d%d",&n,&d);
    ans[0]=n/d;
    if(d*ans[0]==n)
    {
        printf("%d.0\n",ans[0]);
        return 0;
    }
    int temp=ans[0];
    while(temp)
        c++,temp/=10;
    if(!c)c=1;
    c++;
    z=gcd(n,d);
    n/=z;
    d/=z;
    w=len(d);
    n-=ans[0]*d;
    for(;l<=w;l++)
    {
        n*=10;
        ans[l]=n/d;
        n-=ans[l]*d;
    }
    loop[ll++]=n;
    while(n)
    {
        n*=10;
        ans[l]=n/d;
        n-=ans[l++]*d;
        loop[ll++]=n;
        if(loop[ll-1]==loop[0])
            break;
    }
    printf("%d.",ans[0]);
    for(int i=1;i<=w;i++,c++)
    {
        if(c==76)
            printf("\n"),c=0;
        printf("%d",ans[i]);
    }
    //cout<<endl<<w<<' '<<l<<endl;
    if(l>w+1)
    {
        if(c==76)
            printf("\n"),c=0;
        printf("(");
        c++;
        for(int i=w+1;i<l;i++,c++)
        {
            if(c==76)
                printf("\n"),c=0;
            printf("%d",ans[i]);
        }
        if(c==76)
            printf("\n"),c=0;
        printf(")\n");
    }
    else
        printf("\n");
    return 0;
}

你可能感兴趣的:(C++,USACO)