POJ1001解题思路测试样本及程序

题目

Description

Problems involving the computation of exact values of very large magnitude and precision are common. For example, the computation of the national debt is a taxing experience for many computer systems
This problem requires that you write a program to compute the exact value of Rn where R is a real number ( 0.0 < R < 99.999 ) and n is an integer such that 0 < n <= 25.

Input

The input will consist of a set of pairs of values for R and n. The R value will occupy columns 1 through 6, and the n value will be in columns 8 and 9

Output

The output will consist of one line for each line of input giving the exact value of R^n. Leading zeros should be suppressed in the output. Insignificant trailing zeros must not be printed. Don’t print the decimal point if the result is an integer.

Sample Input

95.123 12
0.4321 20
5.1234 15
6.7592 9
98.999 10
1.0100 12

Sample Output

548815620517731830194541.899025343415715973535967221869852721
.00000005148554641076956121994511276767154838481760200726351203835429763013462401
43992025569.928573701266488041146654993318703707511666295476720493953024
29448126.764121021618164430206909037173276672
90429072743629540498.107596019456651774561044010001
1.126825030131969720661201

解题思路

1、首先需要了解整数的高精度乘法
https://blog.csdn.net/qiongyaoxinpo/article/details/89378799
2、再这基础上了解整数的高精度指数乘法
https://blog.csdn.net/qiongyaoxinpo/article/details/89394674
3、在理解了高精度的指数乘法之后,剩下的就是对输入数据的判断以及数据的输出格式
4、判断是否为小数的最简单方法就是判断是否输入了小数点,若输入为整型,则按照上述已实现的方法进行输出即可,若为小数,则将需将小数点去掉,转换为新的字符串,并记录小数点的位置
5、以下均为小数的处理思路。去除字符串中小数点后的无效0以及去除字符串种小数有效数字前的无效0
6、带入高精度指数乘法中得到结果
7、以小数形式进行输出,分3种情况进行讨论
小数点位置n阶后的位数等于高精度指数乘法得到结果的位数,处理方法为:先输出小数点,后依次输出结果
小数点位置
n阶后的位数大于高精度指数乘法得到结果的位数,处理方法为:先输出小数点,补齐缺失位置的0,后依次输出结果
小数点位置*n阶后的位数小于高精度指数乘法得到结果的位数,处理方法为:依次输出结果,在相应小数点位置补上小数点

测试样本

除了POJ1001给出的6组样本外,并不一定能够被accepted,更需要其他的边缘数据进行测试,博主在完成程序之后,被以下2组数据给拯救:1、r=0.01 n=1; 2、r = 10.000 n = 1;

程序

以下程序能够直接在vs2015社区版中实现,并且被POJ1001accepted,关键步骤都有详细注释

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string.h>
using namespace std;

#define Length 6

int *Str2int(char *str);
char *Int2str(int *num, int len);
char *Multi(char *s1, char *s2)
{
	char *s;
	int i, j, *c, *a, *b;
	int len, la, lb;
	la = strlen(s1);//统计字符串长度,不包括结束符'\0'
	lb = strlen(s2);
	a = Str2int(s1);//字符转整型
	b = Str2int(s2);
	len = la + lb;
	s = (char *)malloc((len) * sizeof(char));
	c = (int *)malloc((len) * sizeof(int));
	memset(c, 0, sizeof(int)*len);
	memset(s, 0, sizeof(char)*len);
	/*高精度乘法的重点,按照人手工进行乘法运算的方式,通过进位的方法计算结果的每一位的值*/
	for (i = 0; i<la; i++)//整数a的每一位与b的所有位分别相乘
		for (j = 0; j < lb; j++)
		{
			c[i + j] += a[i] * b[j];//在c[i+j]的位置加上a的第i位与b的第j位的积
			c[i + j + 1] += c[i + j] / 10;//在下一位的位置进位
			c[i + j] = c[i + j] % 10;//在当前位置保留除以10后余数
		}
	s = Int2str(c, len);//整型转字符
	return s;
}
char *Exp(char *s, int n)
{
	char *d;
	int i, lens, pos = -1, j = 0,lend,zn,lent,k;
	char *dec;
	lens = strlen(s);
	d = (char *)malloc((lens*n) * sizeof(char));
	dec = (char *)malloc((lens*n) * sizeof(char));
	memset(dec, 0, sizeof(char)*lens*n);
	memset(d, 0, sizeof(char)*lens*n);
	for (i = 0; i < lens; i++)//判断是否为小数,若有小数点则记录位置
		if (s[i] == '.')
			pos = lens - i - 1;
	if (pos != -1)//若有小数点,则将小数点清除,否则不进行操作
	{
		for (i = 0; i < lens; i++)
			if (s[i] != '.')
				dec[j++] = s[i];
		dec[j] = '\0';
		lent = strlen(dec);
		k = pos;
		for (i = 0; i < k; i++)//去掉小数点后面无效的0
			if (dec[lent - i -1] == '0')
			{
				dec[lent - i -1] = '\0';
				pos--;
			}
			else
				break;
		dec = dec + strspn(dec, "0");//除去小数前面无效的0
		//strspn:检索字符串realNumString中第一个不在字符串"0"中出现的字符下标
		strcpy(s, dec);
	}
	if (n == 1)
		d = s;
	else if (n>=2)//若阶次大于2,则进行n-1次自身相乘过程
	{
		d = s;
		for (i = 0; i < n - 1; i++)
		{
			d = Multi(d, s);//n-1次高精度乘法过程
		}
	}
	lend = strlen(d);
	if (lend == pos*n)//小数点位置*n阶后的位数等于高精度指数乘法得到结果的位数
	{
		j = 0;
		dec[j] = '.';
		for (i = 0; i < lend; i++)
		{
			dec[++j] = d[i];
		}
		dec[++j] = '\0';
	}
	else if (lend < pos*n)//小数点位置*n阶后的位数大于高精度指数乘法得到结果的位数
	{
		j = 0;
		zn = pos*n - lend;
		dec[j] = '.';
		for (i= 0; i<zn; i++)
			dec[++j] = '0';
		for (i = 0; i < lend; i++)
		{
			dec[++j] = d[i];
		}
		dec[++j] = '\0';
	}
	else//小数点位置*n阶后的位数小于高精度指数乘法得到结果的位数
	{
		j =0 ;
		zn = lend - pos * n;
		for (i = 0; i < lend; i++)
			if (i == zn)
			{
				dec[j++] = '.';
				dec[j++] = d[i];
			}
			else
				dec[j++] = d[i];
		dec[j] = '\0';
	}
	return dec;
}
int main()
{
	char *s1, *s;//指针为实参,可以认为是全局变量
	int n;
	s1 = (char *)malloc(Length * sizeof(char));//使用指针进行操作时,需要先分配内存
	memset(s1, 0, sizeof(char)*(Length));//初始化分配的内存,置0
	while (cin >> s1 >> n)
	{
		s = Exp(s1, n);//指数乘法
		cout << s << endl;
	}
}
int *Str2int(char *str)
{
	int len, i;
	int *num;
	len = strlen(str);
	num = (int *)malloc(len * sizeof(int));
	memset(num, 0, len * sizeof(int));
	for (i = 0; i < len; i++)//对每一位字符进行倒序存放
		num[i] = str[len - i - 1] - '0';//以ASCII码值进行相减,再转换成整型
	return num;
}
char *Int2str(int *num, int len)
{
	int i;
	char *res;
	res = (char *)malloc(len * sizeof(char));
	memset(res, 0, len * sizeof(char));
	while (num[len - 1] == 0 && len>1)//2个数想乘,结果位数必定小于等于2者位数之和
	{                               //大于等于2者位数之和-1
		len--;
	}
	for (i = 0; i < len; i++)//以ASCII码值进行相加,再转换乘字符串形式
	{
		res[i] = num[len - 1 - i] + '0';
	}
	res[len] = '\0';
	return res;
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Problems involving the computation of exact values of very large magnitude and precision are common. For example, the computation of the national debt is a taxing experience for many computer systems. This problem requires that you write a program to compute the exact value of Rn where R is a real number ( 0.0 < R < 99.999 ) and n is an integer such that 0 < n <= 25. 输入说明 The input will consist of a set of pairs of values for R and n. The R value will occupy columns 1 through 6, and the n value will be in columns 8 and 9. 输出说明 The output will consist of one line for each line of input giving the exact value of R^n. Leading zeros should be suppressed in the output. Insignificant trailing zeros must not be printed. Don't print the decimal point if the result is an integer. 输入样例 95.123 12 0.4321 20 5.1234 15 6.7592 9 98.999 10 1.0100 12 输出样例 548815620517731830194541.899025343415715973535967221869852721 .00000005148554641076956121994511276767154838481760200726351203835429763013462401 43992025569.928573701266488041146654993318703707511666295476720493953024 29448126.764121021618164430206909037173276672 90429072743629540498.107596019456651774561044010001 1.126825030131969720661201 小提示 If you don't know how to determine wheather encounted the end of input: s is a string and n is an integer C++ while(cin>>s>>n) { ... } c while(scanf("%s%d",s,&n)==2) //to see if the scanf read in as many items as you want /*while(scanf(%s%d",s,&n)!=EOF) //this also work */ { ... } 来源 East Central North America 1988 北大OJ平台(代理
题目描述: 给定一个 $N \times M$ 的矩阵,其中 "." 表示水洼,"W" 表示水。请计算有多少个水洼。 解题思路: 这是一道非常经典的搜索题目。我们可以使用 DFS 或 BFS 进行求解。 首先,我们需要遍历整个矩阵,当我们遇到一个 "." 时,我们就从该点开始向四周搜索,将所有相邻的 "." 变为 "W" ,并继续向下搜索。每次搜索完毕后,我们就可以找到一个完整的水洼,计数器加一。最后,当我们遍历完整个矩阵后,就可以得到所有的水洼数量。 代码实现: 使用 DFS 进行搜索: ```c++ #include <iostream> using namespace std; const int maxn = 110; char field[maxn][maxn]; bool vis[maxn][maxn]; int n, m; void dfs(int x, int y) { vis[x][y] = true; for (int dx = -1; dx <= 1; dx++) { for (int dy = -1; dy <= 1; dy++) { int nx = x + dx, ny = y + dy; if (nx >= 0 && nx < n && ny >= 0 && ny < m && !vis[nx][ny] && field[nx][ny] == '.') { dfs(nx, ny); } } } } int main() { cin >> n >> m; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { cin >> field[i][j]; } } int res = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (!vis[i][j] && field[i][j] == '.') { dfs(i, j); res++; } } } cout << res << endl; return 0; } ``` 使用 BFS 进行搜索: ```c++ #include <iostream> #include <queue> using namespace std; const int maxn = 110; char field[maxn][maxn]; bool vis[maxn][maxn]; int n, m; void bfs(int x, int y) { queue<pair<int, int>> q; q.push(make_pair(x, y)); vis[x][y] = true; while (!q.empty()) { int cx = q.front().first, cy = q.front().second; q.pop(); for (int dx = -1; dx <= 1; dx++) { for (int dy = -1; dy <= 1; dy++) { int nx = cx + dx, ny = cy + dy; if (nx >= 0 && nx < n && ny >= 0 && ny < m && !vis[nx][ny] && field[nx][ny] == '.') { q.push(make_pair(nx, ny)); vis[nx][ny] = true; } } } } } int main() { cin >> n >> m; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { cin >> field[i][j]; } } int res = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (!vis[i][j] && field[i][j] == '.') { bfs(i, j); res++; } } } cout << res << endl; return 0; } ``` 时间复杂度: 两种方法的时间复杂度均为 $O(NM)$,其中 N 和 M 分别为矩阵的行数和列数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值