算法竞赛入门经典(第2版)紫书 第二章笔记

习题1-4 正弦和余弦(sin和cos)

输入正整数n(n<360),输出n度的正弦、余弦函数值。提示:使用数学函数。

#include<stdio.h>
#include<math.h>
#define PI 3.1415
int main()
{
	int n;
	double nsin,ncos;
	scanf("%d",&n);
	nsin = sin(n*PI/180);
	ncos = cos(n*PI/180);
	//正弦sin与余弦cos函数的参数为弧度制,则需要将输入的值转换为弧度制
	//转弧度方法:n*PI/180;
	printf("%.4f %.4f\n",nsin,ncos);
	return 0;
}

例题2-1 aabb

输出所有形如aabb的4位完全平方数(即前两位数字相等,后两位数字也相等)。

#include <iostream>
using namespace std;

int main(){
	for(int i = 1; ; i++){
		int n = i*i;
		
		if(n<1000) continue;
		if(n>9999) break;
		
		int aa = n/100;
		int bb = n%100;
		
		if(aa%10==aa/10 && bb%10==bb/10)
			cout << n << endl;
		
	}
	return 0;
} 

例题2-2 3n+1问题

猜想(4):对于任意大于1的自然数n,若n为奇数,则将n变为3n+1,否则变为n的一半。
经过若干次这样的变换,一定会使n变为1。例如,3→10→5→16→8→4→2→1。
输入n,输出变换的次数。n≤109
样例输入:
3
样例输出:
7

#include <iostream>
using namespace std;

int main(){
	int n,res = 0;
	cin >> n;
	longlong t = n;	///
	
	while(t > 1){
		if(l%2 == 1) t = 3*t+1;
		else t /= 2;
		res++;
	}
	
	cout << res << endl;
	return 0;
} 

例题2-3 近似计算

计算:π/4 = 1 - 1/3 + 1/5 -1/7 +…,直到最后一项小于10-6

#include <iostream>
#include <cstdio>
using namespace std;

int main(){
	double sum = 0;
	
	for(int i=0; ; i++){
		double t = 1.0 / (2*i+1);
		
		if(i % 2 == 0) sum -= t;
		else sum += t;
		
		if(t < 1e-6) break; 
	}
	
	printf("%.6f\n", sum);
	return 0;
} 

例题2-4 阶乘之和

输入n,计算S=1!+2!+3!+…+n!的末6位(不含前导0)。n≤106,n!表示前n个正整数之积。
样例输入:
10
样例输出:
37913

#include <iostream>
#include <cstdio>
using namespace std;

const int MOD = 1000000;

int main(){
	int n, S = 0;
	cin >> n;
	if(n > 25) n = 25;	//25!末尾有6个0,所以从第25项开始,后面的所有项都不会影响和的末6位数字
	
	for(int i=1; i<=n; i++){
		int factorial = 1;
		
		for(int j=1; j<=i; j++){
			factorial = (factorial * j % MOD);
		}
		S = (S + factorial) % MOD;
	}
	
	cout << S << endl;
	return 0;
} 

提示:要计算只包含加法、减法和乘法的整数表达式除以正整数n的余数,可以在每步计算之后对n取余,结果不变。

例题2-5 数据统计

题目描述:
 输入一些整数,求出它们的最小值、最大值和平均值(保留3位小数)。输入保证这些数都是不超过1000的整数。
样例输入:
2 8 3 5 1 7 3 6
样例输出:
1 8 4.375

#include<iostream>
#include<cstdio>
using namespace std;

#define INF 100000000

int main(){
	int x,n = 0, min = INF, max = -INF, sum = 0;
	
	while(scanf("%d",&x) != EOF){
		sum += x;
		if(x > max) max = x;
		if(x < min) min = x;
		n++;
	}
	
	printf("%d %d %.3f", min, max,(double)sum/n);
	return 0;
}

习题2-1 水仙花数(daffodil)

输出100~999中的所有水仙花数。若3位数ABC满足ABC=A3+B3+C3,则称其为水仙花数。例如153=13+53+33,所以153是水仙花数。

#include <iostream>
using namespace std;

int main(){
	
	for(int i=100; i<=999; i++){
		int A = i/100, B = i/10%10, C = i%10;
		if(A*A*A + B*B*B + C*C*C == i)
			cout << i << " ";
	} 
	return 0;
}

习题2-2 韩信点兵(hanxin)

相传韩信才智过人,从不直接清点自己军队的人数,只要让士兵先后以三人一排、五人一排、七人一排地变换队形,而他每次只掠一眼队伍的排尾就知道总人数了。输入包含多组数据,每组数据包含3个非负整数a,b,c,表示每种队形排尾的人数(a<3,b<5,c<7),输出总人数的最小值(或报告无解)。已知总人数不小于10,不超过100。输入到文件结束为止。
样例输入:
2 1 6
2 1 3
样例输出:
Case 1: 41
Case 2: No answer

#include <iostream>
#include <cstdio>
using namespace std;
 
int main(){
	int a,b,c;
	int k = 0;
	int i;
	
	while(scanf("%d%d%d",&a, &b, &c) == 3){
		for(i=10; i<=100; i++){
			if(i%3==a && i%5==b && i%7==c){
				printf("Case %d: %d\n", ++k, i);
				break;
			}
		}
		if(i == 101) printf("Case %d: No answer\n", ++k);
	}
	
	return 0;
}

习题2-3 倒三角形(triangle)

输入正整数n≤20,输出一个n层的倒三角形。例如,n=5时输出如下:

#########
 #######
  #####
   ###
    #
#include <iostream>
using namespace std;
 
int main(){
	int n;
	cin >> n;
	for(int i=0; i<n; i++){
		for(int j = 0; j<i; j++)
			cout << ' ';
		for(int j = i; j<2*n-1-i; j++)
			cout << '#';
		cout << endl;
	}
	return 0;
}

习题2-4 子序列(subsequence)

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

#include <iostream>
#include <cstdio>
using namespace std;
 
int main(){
	int n,m;
	int i, k = 0;
	double sum = 0.0;
	scanf("%d%d", &n,&m);
	
	while(n!=0 && m!=0){ 
		for(i = n; i<=m; i++){
			sum += 1.0/i/i; //注意不能sum = 1.0/(i*i) 会溢出
		}
		printf("Case %d: %.5lf", ++k, sum);
		scanf("%d%d", &n,&m);
	}
	return 0;
}

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

输入正整数a,b,c,输出a/b的小数形式,精确到小数点后c位。a,b≤106,c≤100。输入包含多组数据,结束标记为a=b=c=0。
样例输入:
1 6 4
0 0 0
样例输出:
Case 1: 0.1667

#include <iostream>
#include <cstdio>
#include <cmath>

using namespace std;

int main(){
	int a, b, c;
	int cas = 0;
	
	while(scanf("%d%d%d", &a, &b, &c)){
		if(a==0 && b==0 && c==0) break;
		
		if(c > 1){
			int x = floor((double)a / b);
			printf("Case %d: %d.", ++cas, x); //输出整数部分 
			
			int i, s;
			for(i=1; i<c; i++){
				a = a%b; //在第一次循环中拿到第一个余数 
				a = a*10; //借一位 
				s = a/b; //得到小数点后第一位的值 
				a = a%b; //得到第二个余数 
				printf("%d",s);
			}
			a = a*10;
			s = floor((double)a/b + 0.5);
			printf("%d",s);
			printf("\n");
		} 
		
		else{
			printf("%.1f",(double)a/b);
		}
	}
	return 0;
} 

习题2-6 排列(permutation)

用1,2,3,…,9组成3个三位数abc,def和ghi,每个数字恰好使用一次,要求abc:def:ghi=1:2:3。按照“abc def ghi”的格式输出所有解,每行一个解。

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

using namespace std;

int main(){
	int abc, def, ghi, sum = 0, i;
	int s[10];
	
	for(abc=123; abc<=329; abc++){//abc的数据范围:最小123,最大987/3=329 
		memset(s,0,sizeof(s));//memset函数可以对数组,指针进行初始化 
		def = abc*2;
		ghi = abc*3;
		
		//将已用的数字在数组s[]中标记为1; 
		s[abc/100] = s[abc/10%10] = s[abc%10] = 1;
		s[def/100] = s[def/10%10] = s[def%10] = 1;
		s[ghi/100] = s[ghi/10%10] = s[ghi%10] = 1;
		
		for(int i=1; i<=9; i++)
			sum += s[i];
		if(sum == 9)
			printf("%d %d %d\n",abc, def, ghi);
			
		//再次进行循环时,要记得对sum和s数组进行初始化 
		sum = 0;
		memset(s,0,sizeof(s));
	}
	return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值