1. 程式人生 > >USACO2.4.5 Fractions to Decimals 分數化小數(模擬)

USACO2.4.5 Fractions to Decimals 分數化小數(模擬)

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; }