USACO2.4.5 Fractions to Decimals 分数化小数(模拟)

时间:2021-10-27 08:19:38

Description
写一个程序,输入一个形如N/D的分数(N是分子,D是分母),输出它的小数形式。 如果小数有循环节的话,把循环节放在一对圆括号中。例如, 1/3 = .33333333 写成0.(3) 41/333 = 0.123123123… 写成0.(123) 用xxx.0 成表示整数 典型的转化例子: 1/3 = 0.(3) 22/5 = 4.4 1/7 = 0.(142857) 2/2 = 1.0 3/8 = 0.375 45/56 = 0.803(571428)

Input
小数的表示方法上面说的很明白了,如果输出的长度超过76个字符,每行输出76个。

Output
45 56

Sample Input
0.803(571428)


题意很明显了,说下思路吧:
首先我们知道这个数只有三种可能

  • 纯循环小数(如0.333333…)
  • 循环小数(如32.479797979…)
  • 小数(如0.375)
    那么我们把两部分拆分开来好了,假设它就是一个循环小数,我们先把它拆分成非循环部分和循环部分,然后统一输出就行了,对于每次的除数和被除数,我们都将这个数对记录下来,如果它再次出现,那么说明它一定是循环的(因为经过n次相除后又回到了起点),以此为突破点拆分然后输出即可
#include <map> #include <queue> #include <cstdlib> #include <cmath> #include <cstdio> #include <string> #include <cstring> #include <fstream> #include <iostream> #include <sstream> #include <algorithm> #define lowbit(a) (a&(-a)) #define _mid(a,b) ((a+b)/2) #define _mem(a,b) memset(a,0,(b+3)<<2) #define fori(a) for(int i=0;i<a;i++) #define forj(a) for(int j=0;j<a;j++) #define ifor(a) for(int i=1;i<=a;i++) #define jfor(a) for(int j=1;j<=a;j++) #define mem(a,b) memset(a,b,sizeof(a)) #define IN freopen("in.txt","r",stdin) #define OUT freopen("out.txt","w",stdout) #define IO do{\ ios::sync_with_stdio(false);\ cin.tie(0);\ cout.tie(0);}while(0) #define mp(a,b) make_pair(a,b) #define debug(a) cout <<(a) << endl using namespace std; typedef long long ll; const int maxn = 2*1e5+9; const int INF = 0x3f3f3f3f; const int inf = 0x3f; const double EPS = 1e-7; const double Pi = acos(-1); const int MOD = 1e9+7; int c[maxn]; pair <int,int>buf; map< pair<int,int>,int>q; //标记数对是否出现,如果a/b为纯循环小数的话,<a,b>这个数对一定会反复出现 int getnum(int a,int b,int flag) { //flag = 1时计算循环部分,否则计算非循环部分 mem(c,0); q.clear(); int cnt = 0; while(cnt <= 1e5) { //迭代相除  buf.first = a; buf.second = b; if(q[buf]) { //如果数对用过,则证明从这里开始循环了 if(flag) return cnt-1; break; } q[buf] = cnt; /*相除*************/ if(a > b) c[cnt++] = a/b,a %= b; else if(a==b) { buf.first = 0; c[cnt++] = 1; return cnt; } else c[cnt++] = 0; a *= 10; /****************/ } return q[buf]; } int jugecnt(int a){int ans = 0;while(a) ans++,a/=10;return ans?ans:1;} //判断数组内存的数字位数 int main() { int a,b; int cnt = 0; bool flag = false; cin >>a >> b; int cntline = 0; //记录每行输出了几个字符 int e = getnum(a,b,0); //算出不循环部分,然后剩下的两个数相除一定是循环小数 fori(e) { if(i==1) cout <<".",cntline++; cout << c[i],cntline+=jugecnt(c[i]); } if(e >= 2) flag = true; if(e <= 1) cout <<".",cntline++; e = getnum(buf.first,buf.second,1); // 计算循环部分 if(!(e<=1&&c[e-1]==0)){ cout <<"(",cntline++; fori(e){ cout << c[i],cntline+=jugecnt(c[i]); if(cntline ==76){ cout << endl; cntline = 0; } } cout <<")",cntline++; } else if(!flag) fori(e){ cout << c[i],cntline++; if(cntline ==76){ cout << endl; cntline = 0; } } cout <<endl; return 0; }