《算法竞赛入门经典》2.0_第二章_bonus

习题2-4 子序列的和(subsequence)

输入两个正整数n<m<106,输出 ,保留5位小数。输入包含多组数据, 结束标记为n=m=0。提示:本题有陷阱。
样例输入:
2 4
65536 655360
0 0
样例输出:
Case 1: 0.42361
Case 2: 0.00001

收获

这题看起来简单,但是敲完,然后书本给的测试数据都过不了。
输出:

2 4
Case 1: 0.42361
65536 655360
Case 2: inf

自己先认真思考,嗯真的挺认真的,想不出来,然后查阅了资料,看了前辈的各种见解。发现就是前几天刷OJ的一个问题,先乘后除然后数据溢出了。inf表示infinite(无穷大),超过浮点数的表示范围,就是阶码部分溢出了。(我心里想着这不是没溢出,数不会很大来着,既然它解释说阶码部分溢出,那还能理解一点点)。解决方法就是:

			//sum += (1.0) / (i * i); 会溢出
			//改成先除法即可
			sum += (1.0) / (i*1.0) / (i*1.0);

习题2-5 分数化小数(decimal)

输入正整数a,b,c,输出a/b的小数形式,精确到小数点后c位。a,b<=10^6,c<=100。输入包含多组数据,结束标记为a=b=c=0。

样例输入:

1 6 4

0 0 0

样例输出:

Case 1: 0.1667

哔哔赖赖

我本以为用c++的保留小数点后的位数setprecision()函数即可,然后看了一些博客,说double最多精确到小数点后16位,再多没有了!

自己试了一下,输出三分之一,是这样!然后学到了,可以采用自己模拟除法的方法,就可以解决这个问题,这样想输出小数后10000位都不是问题。
1/3保留小数点后30位的结果

乘10取余法——这个方法就是先算整数部分,剩下的小数部分不断乘10取余即可。这里放个例子,会更容易理解:1.0 / 8.0, 整数部分为0,小数部分计算:1乘10 再除以8,整除得1,取余得余数2。1就是第一位小数了,剩下继续 2乘10再除以8,整除得2,取余得余数4。继续,4乘10 再除以8,整除得5,取余得0,计算结束,得值0.125

代码实现

#include <iostream>
//#include <iomanip> //cout输出小数后的位数 ,这是改动前的代码 
using namespace std;

int main() {
	int a,b,c;
	while (scanf("%d%d%d", &a, &b ,&c) != EOF) {
		
		if(a==0 && b==0 && c==0) break;
		
//		double res = (a*1.0) / b;
//		cout.setf(ios::fixed); //自动补尾数的0
//		cout << fixed << setprecision(c) << res << endl; 
		
		int z = a / b;	//整数部分 
		a = a -  z * b;	//去掉能整除部分后的a的值
		cout << z << "."; //输出整数和小数点
		//由于最后一位小数要四舍五入,所以我们先输出到第(c-1)位 
		for (int i = 0; i < c-1; i++) {
			cout << a * 10 / b;
			a  %=  b; 
		} 
		//处理最后一位小数,四舍五入
		int last , judge;
		last = a * 10 / b;
		a %= b;
		judge = a * 10 / b;
		if (judge >= 5) last++;
		cout << last << endl;
	}
	return 0;
}

输出

没有描述

PS:突然在想,我写博客的初衷是什么呢?

嗯,是想记录自己的成长过程、收获的点点滴滴,并且想着能把思路写出来,可以加深自己的理解。加油鸭!!!:)

习题2-6 排列(permutation)

用1,2,3,…,9组成3个三位数abc、def、ghi,每个数字恰好使用一次,要求abc:def:ghi = 1:2:3。提示:不必太动脑筋。

嗯,没错!它说不要太动脑筋,我差点就想直接全部把三位数用三个循环遍历一遍了,总共有900900900种情况。。。
但是这代码写得傻就算了,还麻烦,真的是又臭又长,我最终放弃了这个想法,战略性跳过,然后放下书,打游戏去了。

今天搜C++的STL的简介的时候,看到了permutation这个函数,可以输出数组中数的全部排列!!!我去,那我不是直接用!!!用“轮子”真的是美滋滋,下面是代码

代码实现

#include <iostream> 
#include<stdio.h>
#include<algorithm>
using namespace std;
int main(void){
	int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
	//使用C++中的net_permutation函数生成数组的全排列
	do{
		int a = arr[0]*100 + arr[1]*10 + arr[2];
		int b = arr[3]*100 + arr[4]*10 + arr[5];
		int c = arr[6]*100 + arr[7]*10 + arr[8];
		if (a == (b*1.0)/2 && a == (c*1.0)/3) {
			printf("%d%d%d %d%d%d %d%d%d\n", arr[0],arr[1],arr[2],arr[3],arr[4],arr[5],arr[6],arr[7],arr[8]);
		}
	}while(next_permutation(arr, arr + 9));
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值