GCD相关
板子:
1 int gcd(int a, int b) { return b > 0 ? gcd(b, a % b) : a; }
POJ1930
题意:给你一个无限循环小数,给到小数点后 9 位,要求这个数的分数形式。
解法:
要想解决这道题,首先应该了解如何将循环小数化为分数:
一,纯循环小数化分数:循环节的数字除以循环节的位数个 9 组成的整数。例如:
$0.3333……=3/9=1/3$;
$0.285714285714……=285714/999999=2/7$.
二,混循环小数:(例如:$0.24333333……$)不循环部分和循环节构成的的数减去不循环部分的差,再除以循环节位数个 9 添上不循环部分的位数个 0。例如:
$0.24333333…………=(243-24)/900=73/300 $
$0.9545454…………=(954-9)/990=945/990=21/22$
这便是循环小数化成分数的方法,知道这个后,解决这道题也好办了。
代码如下:
1 #pragma GCC optimize(3) 2 #include <time.h> 3 #include <algorithm> 4 #include <bitset> 5 #include <cctype> 6 #include <cmath> 7 #include <cstdio> 8 #include <cstdlib> 9 #include <cstring> 10 #include <deque> 11 #include <functional> 12 #include <iostream> 13 #include <map> 14 #include <queue> 15 #include <set> 16 #include <sstream> 17 #include <stack> 18 #include <string> 19 #include <utility> 20 #include <vector> 21 using namespace std; 22 const double EPS = 1e-9; 23 const int INF = 2147483647; 24 const long long LLINF = 9223372036854775807; 25 const double PI = acos(-1.0); 26 27 inline int READ() { 28 char ch; 29 while ((ch = getchar()) < 48 || 57 < ch) 30 ; 31 int ans = ch - 48; 32 while (48 <= (ch = getchar()) && ch <= 57) 33 ans = (ans << 3) + (ans << 1) + ch - 48; 34 return ans; 35 } 36 37 #define REP(i, a, b) for (int i = (a); i <= (b); i++) 38 #define PER(i, a, b) for (int i = (a); i >= (b); i--) 39 #define FOREACH(i, t) for (typeof(t.begin()) i = t.begin(); i != t.end(); i++) 40 #define MP(x, y) make_pair(x, y) 41 #define PB(x) push_back(x) 42 #define SET(a) memset(a, -1, sizeof(a)) 43 #define CLR(a) memset(a, 0, sizeof(a)) 44 #define MEM(a, x) memset(a, x, sizeof(a)) 45 #define ALL(x) begin(x), end(x) 46 #define LL long long 47 #define Lson (index * 2) 48 #define Rson (index * 2 + 1) 49 #define pii pair<int, int> 50 #define pll pair<LL, LL> 51 #define MOD ((int)1000000007) 52 #define MAXN 20 + 5 53 ///**********************************START*********************************/// 54 string ss, sn; 55 56 char s[MAXN], ns[MAXN]; 57 int nex[MAXN]; 58 59 void get_next(char* p, int next[]) { 60 int pLen = strlen(p) + 1; //要求循环节长度时这里才+1 61 next[0] = -1; 62 int k = -1; 63 int j = 0; 64 while (j < pLen - 1) { 65 if (k == -1 || p[j] == p[k]) { 66 ++j; 67 ++k; 68 if (p[j] != p[k]) 69 next[j] = k; 70 else 71 next[j] = next[k]; 72 } else { 73 k = next[k]; 74 } 75 } 76 } 77 78 int gcd(int a, int b) { return b > 0 ? gcd(b, a % b) : a; } 79 80 void cal_cal(int len) { 81 int up = 0, down = 0; 82 for (int i = len - 1; i >= 0; i--) 83 up += int(s[i] - '0') * pow(10, len - i - 1); 84 for (int i = 0; i < len; i++) down += 9 * pow(10, i); 85 int g = gcd(up, down); 86 printf("%d/%d\n", up / g, down / g); 87 return; 88 } 89 90 void cal_cal2(int st, int len) { 91 char tmp[20]; 92 int up = 0, down = 0; 93 int a, b; 94 95 for (int i = 0; i < st; i++) tmp[i] = s[i]; 96 tmp[st] = '\0'; 97 a = atoi(tmp); 98 for (int i = st; i < st + len; i++) tmp[i - st] = s[i]; 99 tmp[len] = '\0'; 100 b = atoi(tmp); 101 102 up = a * pow(10, len) + b - a; 103 int pos = 0; 104 for (int i = 0; i < len; i++) tmp[pos++] = '9'; 105 for (int i = 0; i < st; i++) tmp[pos++] = '0'; 106 down = atoi(tmp); 107 int g = gcd(up, down); 108 printf("%d/%d\n", up / g, down / g); 109 return; 110 } 111 112 int main() { 113 #ifndef ONLINE_JUDGE 114 freopen("input.txt", "r", stdin); 115 #endif // !ONLINE_JUDGE 116 while (cin >> ss) { 117 if (ss.size() == 1) break; 118 int pos = 0; 119 for (int i = 2; ss[i] != '.'; i++) s[pos++] = ss[i]; 120 s[pos] = '\0'; 121 int flag = 0; // 1为全循环,2为混合循环 122 get_next(s, nex); 123 int len = pos - nex[pos]; 124 if (len != pos) { 125 cal_cal(len); 126 } else { 127 int st; 128 for (st = 1; st < pos; st++) { 129 int nlen = 0; 130 for (int i = st; i < pos; i++) { 131 ns[nlen++] = s[i]; 132 } 133 CLR(nex); 134 get_next(ns, nex); 135 if (nlen - nex[nlen] != nlen) { 136 cal_cal2(st, nlen); 137 break; 138 } else 139 continue; 140 } 141 } 142 } 143 return 0; 144 }