HDU 2522 & AOJ 441 & AOJ 364 关于小数和分数的转换

总结一下小数和分数之间精确转换的方法。

首先是分数转换为小数,这个比较简单,先看题 http://acm.hdu.edu.cn/showproblem.php?pid=2522

输入一个n,求1/n的精确表示,如果有循环节只输出最小的一个。

手动模拟一下出发,会发现每次都是上一次除法剩下来的余数*10然后继续下一次计算,什么时候会出现循环呢,显然是余数出现重复的时候。

余数判断重复可以搞一个hash或者set,这里n不是特别大,直接用数组就可以了。

另外写的时候注意一下处理整除的情况。

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int maxn = 1e5 + 10;
bool vis[maxn];

int main() {
	int n, T; scanf("%d", &T);
	while (T--) {
		scanf("%d", &n);
		memset(vis, false, sizeof(vis));
		int num = abs(n), nowmod = 1, nowval;
		vis[1] = true; vis[0] = true;
		if (num == 1) {
			puts("1"); continue;
		}
		if (n < 0) putchar(‘-‘);
		printf("0.");
		while (1) {
			nowval = (nowmod * 10) / num;
			nowmod = (nowmod * 10) % num;
			printf("%d", nowval);
			if (vis[nowmod]) break;
			vis[nowmod] = true;
		}
		putchar(‘\n‘);
	}
	return 0;
}

另外看一下 http://icpc.ahu.edu.cn/OJ/Problem.aspx?id=441

输入两个数A,B(0<A<=B<=1000),精确输出A/B,并且输出最小循环节长度。

处理方法和上面那个一样,使劲除就好了。 长度的处理就是把原来的vis数组给换成是记录上一次这个数出现的位置即可。

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn = 1000 + 10;
int pre_pos[maxn];

int main() {
	int A, B;
	while (scanf("%d%d", &A, &B), A) {
		memset(pre_pos, -1, sizeof(pre_pos));
		A %= B;
		if (A == 0) {
			puts(".\nThis expansion terminates.");
			continue;
		}
		int nowmod = A, nowval, len, nowpos = 0;
		pre_pos[A] = 0;
		bool terminal = false;
		putchar(‘.‘);
		while (1) {
			nowpos++;
			nowval = (nowmod * 10) / B;
			nowmod = (nowmod * 10) % B;
			if (nowval == 0 && nowmod == 0) {
				terminal = true; break;
			}
			printf("%d", nowval);
			if (pre_pos[nowmod] != -1) {
				len = nowpos - pre_pos[nowmod];
				break;
			}
			pre_pos[nowmod] = nowpos;
		}
		putchar(‘\n‘);
		if (terminal) puts("This expansion terminates.");
		else printf("The last %d digits repeat forever.\n", len);
 	}
	return 0;
}

 

然后是给你小数,指定循环节,让你求分数。 http://icpc.ahu.edu.cn/OJ/Problem.aspx?id=364

这类问题比上面那种要麻烦,需要推一下公式。

给你一个小数 N = 0.A(B),括号内的为循环节,假设A的长度为LenA,B的长度为LenB,有

N * 10^LenA = A.(B)  ----> N * 10^LenA - A = 0.(B)

设Y = 0.(B) 有

Y * 10^LenB = B.(B)

Y * 10^LenB - B = 0.(B) = Y

Y = B / (10^LenB - 1) = N * 10^LenA - A

N = (B + A * (10^LenB - 1)) / ( 10^LenA * (10^LenB - 1))

分别计算出分子和分母的值,然后求一下gcd,约分一下就好了。

#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

typedef long long LL;

LL gcd(LL a,LL b) {
    return b == 0 ? a : gcd(b,a % b);
}

LL pow10(LL a) {
    LL ret = 1;
    while(a--) ret *= 10;
    return ret;
}

void display(int a,int b) {
    int n = 0,m = 0,ta = a,tb = b;

    while(ta) {
        n++; ta /= 10;
    }

    while(tb) {
        m++; tb /= 10;
    }

    LL denominator,numerator,div;
    denominator = pow10(n) * (pow10(m) - 1);
    numerator = a * (pow10(m) - 1) + b;
    div = gcd(denominator,numerator);

    cout << numerator / div << "/" << denominator / div << endl;
}

int main() {
    int T; cin >>T;
    while(T--) {
        int a,b; cin >> a >> b;
        display(a,b);
    }
    return 0;
}

  

时间: 2024-11-03 02:09:00

HDU 2522 & AOJ 441 & AOJ 364 关于小数和分数的转换的相关文章

hdu1717 小数化分数2

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1717 小数化分数2 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2921    Accepted Submission(s): 1187 Problem Description Ray 在数学课上听老师说,任何小数都能表示成分数的形式

hdu1717 小数化分数

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1717 小数化分数2 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5375    Accepted Submission(s): 2188 Problem Description Ray 在数学课上听老师说,任何小数都能表示成分数的形式,他

hdu 1717 小数化分数2 (数论)

点我点我点我!!! 接下来要做的就是模拟上述过程了. 静下来想一下自己要得到的信息. 然后拿出来,就可以了,模拟嘛,都是这样的. #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; char str[20]; int gcd(int a,int b) { return a%b==0?b:gcd(b,a%b); }

(hdu step 2.1.8)小数化分数2(小数化分数——包括了循环小数化分数的情况)

题目: 小数化分数2 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2783 Accepted Submission(s): 993   Problem Description Ray 在数学课上听老师说,任何小数都能表示成分数的形式,他开始了化了起来,很快他就完成了,但他又想到一个问题,如何把一个循环小数化成分数呢?请你写一个程序不但可以

小数化分数2

小数化分数2 题目 Problem Description Ray 在数学课上听老师说,任何小数都能表示成分数的形式,他开始了化了起来,很快他就完成了,但他又想到一个问题,如何把一个循环小数化成分数呢? 请你写一个程序不但可以将普通小数化成最简分数,也可以把循环小数化成最简分数. Input 第一行是一个整数N,表示有多少组数据. 每组数据只有一个纯小数,也就是整数部分为0.小数的位数不超过9位,循环部分用()括起来. Output 对每一个对应的小数化成最简分数后输出,占一行. Sample

无限小数转分数POJ1930分析

将无限小数化为分数,有一套简单的公式.使其轻松表示出来. 循环节 例如:0.121212…… 循循环节为12. 公式 这个公式必须将循环节的开头放在十分位.若不是可将原数乘10^x(x为正整数) 就为:12.121212……-0.121212……=12 100倍 - 1倍 =99 (99和12之间一条分数线) 此公式需用两位数字,其中两位数差出一个循环节. 再举一个例子:0.00121212…… 公式就变为:1212.121212……-12.121212……=1200 100000 倍 - 10

HDU1717小数化分数2

小数化分数2 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4278    Accepted Submission(s): 1725 Problem Description Ray 在数学课上听老师说,任何小数都能表示成分数的形式,他开始了化了起来,很快他就完成了,但他又想到一个问题,如何把一个循环小数化成分数呢?请你写一个程序不但可以

HDU 2522 A simple problem

A simple problem Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3368    Accepted Submission(s): 1249 Problem Description Zty很痴迷数学问题..一天,yifenfei出了个数学题想难倒他,让他回答1 / n.但Zty却回答不了^_^.  请大家编程帮助他. In

POJ 1979 POJ 3009 AOJ 0033 AOJ 0118 [搜索类题目][0033贪心模拟]

/** POJ 1979 BFS */ #include <stdio.h> #include <string.h> #include <iostream> #include <queue> using namespace std; const int N = 20 + 5; int mp[N][N]; int sx,sy; int n, m; int vis[3000]; int dirx[] = {0, 1, 0, -1}; int diry[] = {