文章目录
- 7-1 厘米换算英尺英寸 (15分)
- 7-2 然后是几点 (15分)
- 7-3 逆序的三位数 (10分)
- 7-4 BCD解密 (10分)
- 7-5 表格输出 (5分)
- 7-6 混合类型数据格式化输入 (5分)
- 7-7 12-24小时制 (15分)
- 7-8 超速判断 (10分)
- 7-9 用天平找小球 (10分)
- 7-10 计算工资 (15分)
- 7-11 分段计算居民水费 (10分)
- 7-12 两个数的简单计算器 (10分)
- 7-13 日K蜡烛图 (15分)
- 7-14 求整数段和 (15分)
- 7-15 计算圆周率 (15分)
- ★★ 7-16 求符合给定条件的整数集 (15分)
- 7-17 爬动的蠕虫 (15分)
- ★★ 7-18 二分法求多项式单根 (20分)
- ★★ 7-19 支票面额 (15分)
- 7-20 打印九九口诀表 (15分)
- 7-21 求特殊方程的正整数解 (15分)
- ★★ 7-22 龟兔赛跑 (20分)
- ★★★ 7-23 币值转换 (20分) 中文习惯读数字
- 7-24 约分最简分式 (15分)
- 7-25 念数字 (15分)
- ★★ 7-26 单词长度 (15分)
- 7-27 冒泡法排序 (20分)
- 【约瑟夫环】7-28 猴子选大王 (20分)
- ★ 7-29 删除字符串中的子串 (20分)
- 7-30 字符串的冒泡排序 (20分)
- 7-31 字符串循环左移 (20分)
- 7-32 说反话-加强版 (20分)
- 7-33 有理数加法 (15分)
- 7-34 通讯录的录入与显示 (10分)
- 【有理数模板】7-35 有理数均值 (20分)
- 【复数运算】7-36 复数四则运算 (15分)
- ★★★ 7-37 整数分解为若干项之和 (20分)
- ★★★ 7-38 数列求和-加强版 (20分)
7-1 厘米换算英尺英寸 (15分)
如果已知英制长度的英尺foot和英寸inch的值,那么对应的米是(foot+inch/12)×0.3048
。现在,如果用户输入的是厘米数,那么对应英制长度的英尺和英寸是多少呢?别忘了1英尺等于12英寸。
- 输入格式:
输入在一行中给出1个正整数,单位是厘米。 - 输出格式:
在一行中输出这个厘米数对应英制长度的英尺和英寸的整数值,中间用空格分开。
输入样例:
170
输出样例:
5 6
答案:按照题目给出的式子倒推即可。
#include <stdio.h>
int main() {
int cm;
scanf("%d", &cm);
double m = cm * 1.0 / 100.0;
int foot = m / 0.3048;
int inch = (m / 0.3048 - foot) * 12;
printf("%d %d\n", foot, inch);
return 0;
}
7-2 然后是几点 (15分)
有时候人们用四位数字表示一个时间,比如1106表示11点零6分。现在,你的程序要根据起始时间和流逝的时间计算出终止时间。
读入两个数字,第一个数字以这样的四位数字表示当前时间,第二个数字表示分钟数,计算当前时间经过那么多分钟后是几点,结果也表示为四位数字。当小时为个位数时,没有前导的零,即5点30分表示为530。注意,第二个数字表示的分钟数可能超过60,也可能是负数。
-
输入格式:
输入在一行中给出2个整数,分别是四位数字表示的起始时间、以及流逝的分钟数,其间以空格分隔。注意:在起始时间中,当小时为个位数时,没有前导的零,即5点30分表示为530;流逝的分钟数可能超过60,也可能是负数。 -
输出格式:
输出四位数字表示的终止时间,当小时为个位数时,没有前导的零。题目保证起始时间和终止时间在同一天内。
输入样例:
1120 110
输出样例:
1310
答案:数基本单位分钟,每一分钟过去加或减开始时间。
#include <cstdio>
int main() {
int begin, end, elipse;
scanf("%d%d", &begin, &elipse);
int min = begin % 100, hour = begin / 100; // 开始时间
if (elipse >= 0) {
while (elipse) {
min++, elipse--;
if (min >= 60) hour++, min = 0;
}
} else {
while (elipse) {
min--, elipse++;
if (min < 0) hour--, min = 59;
}
}
printf("%d%02d", hour, min);
return 0;
}
7-3 逆序的三位数 (10分)
程序每次读入一个正3位数,然后输出按位逆序的数字。注意:当输入的数字含有结尾的0时,输出不应带有前导的0。比如输入700,输出应该是7。
- 输入格式:每个测试是一个3位的正整数。
- 输出格式:输出按位逆序的数。
输入样例:
123
输出样例:
321
答案:得到逆序的数再输出。
#include <cstdio>
int main() {
int n;
scanf("%d", &n);
int ans = 0;
while (n) {
ans = ans * 10 + n % 10;
n /= 10;
}
printf("%d\n", ans);
return 0;
}
7-4 BCD解密 (10分)
BCD数是用一个字节来表达两位十进制的数,每四个比特表示一位。所以如果一个BCD数的十六进制是0x12,它表达的就是十进制的12。但是小明没学过BCD,把所有的BCD数都当作二进制数转换成十进制输出了。于是BCD的0x12被输出成了十进制的18了!
现在,你的程序要读入这个错误的十进制数,然后输出正确的十进制数。提示:你可以把18转换回0x12,然后再转换回12。
- 输入格式:
输入在一行中给出一个[0, 153]范围内的正整数,保证能转换回有效的BCD数,也就是说这个整数转换成十六进制时不会出现A-F的数字。
输出格式:
输出对应的十进制数。
输入样例:
18
输出样例:
12
答案:简单的进制转换,这里用了递归的写法。
#include <cstdio>
// 就是十进制转换为16进制
void solve(int n) {
if (n / 16 == 0) printf("%d", n);
else {
solve(n / 16);
printf("%d", n % 16);
}
}
int main() {
int n;
scanf("%d", &n);
solve(n);
return 0;
}
7-5 表格输出 (5分)
本题要求编写程序,按照规定格式输出表格。
- 输入格式:
本题目没有输入。 - 输出格式:
要求严格按照给出的格式输出下列表格:
------------------------------------
Province Area(km2) Pop.(10K)
------------------------------------
Anhui 139600.00 6461.00
Beijing 16410.54 1180.70
Chongqing 82400.00 3144.23
Shanghai 6340.50 1360.26
Zhejiang 101800.00 4894.00
------------------------------------
答案:直接输出即可。
#include <cstdio>
int main() {
printf("------------------------------------\n");
printf("Province Area(km2) Pop.(10K)\n");
printf("------------------------------------\n");
printf("Anhui 139600.00 6461.00\n");
printf("Beijing 16410.54 1180.70\n");
printf("Chongqing 82400.00 3144.23\n");
printf("Shanghai 6340.50 1360.26\n");
printf("Zhejiang 101800.00 4894.00\n");
printf("------------------------------------\n");
return 0;
}
7-6 混合类型数据格式化输入 (5分)
本题要求编写程序,顺序读入浮点数1、整数、字符、浮点数2,再按照字符、整数、浮点数1、浮点数2的顺序输出。
- 输入格式:
输入在一行中顺序给出浮点数1、整数、字符、浮点数2,其间以1个空格分隔。 - 输出格式:
在一行中按照字符、整数、浮点数1、浮点数2的顺序输出,其中浮点数保留小数点后2位。
输入样例:
2.12 88 c 4.7
输出样例:
c 88 2.12 4.70
答案:照格式输入输出。
#include <iostream>
#include <cstdio>
using namespace std;
int main() {
double d;
int i;
char c;
double d2;
cin >> d >> i >> c >> d2;
printf("%c %d %.2f %.2f\n", c, i, d, d2);
return 0;
}
7-7 12-24小时制 (15分)
编写一个程序,要求用户输入24小时制的时间,然后显示12小时制的时间。
- 输入格式:
输入在一行中给出带有中间的:符号(半角的冒号)的24小时制的时间,如12:34表示12点34分。当小时或分钟数小于10时,均没有前导的零,如5:6表示5点零6分。
提示:在scanf的格式字符串中加入:,让scanf来处理这个冒号。 - 输出格式:
在一行中输出这个时间对应的12小时制的时间,数字部分格式与输入的相同,然后跟上空格,再跟上表示上午的字符串AM或表示下午的字符串PM。如5:6 PM表示下午5点零6分。注意,在英文的习惯中,中午12点被认为是下午,所以24小时制的12:00就是12小时制的12:0 PM;而0点被认为是第二天的时间,所以是0:0 AM。
输入样例:
21:11
输出样例:
9:11 PM
答案:简单判断上午下午即可。
#include <iostream>
#include <cstdio>
using namespace std;
int main() {
int hours, mins;
scanf("%d:%d", &hours, &mins);
int am = hours < 12 ? 1 : 0;
if (am) printf("%d:%d AM\n", hours, mins);
else printf("%d:%d PM\n", hours == 12 ? 12 : hours % 12, mins); // 12点特判
return 0;
}
7-8 超速判断 (10分)
模拟交通警察的雷达测速仪。输入汽车速度,如果速度超出60 mph,则显示“Speeding”,否则显示“OK”。
- 输入格式:
输入在一行中给出1个不超过500的非负整数,即雷达测到的车速。 - 输出格式:
在一行中输出测速仪显示结果,格式为:Speed: V - S,其中V是车速,S或者是Speeding、或者是OK。
输入样例1:
40
输出样例1:
Speed: 40 - OK
输入样例2:
75
输出样例2:
Speed: 75 - Speeding
答案:简单判断。
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
cout << "Speed: " << n << (n > 60 ? " - Speeding" : " - OK");
return 0;
}
7-9 用天平找小球 (10分)
三个球A、B、C,大小形状相同且其中有一个球与其他球重量不同。要求找出这个不一样的球。
- 输入格式:
输入在一行中给出3个正整数,顺序对应球A、B、C的重量。 - 输出格式:
在一行中输出唯一的那个不一样的球。
输入样例:
1 1 2
输出样例:
C
答案:
#include <cstdio>
#include <iostream>
using namespace std;
int main() {
int i, j, k;
cin >> i >> j >> k;
if (i == j) printf("C");
else if (i == k) printf("B");
else printf("A");
return 0;
}
7-10 计算工资 (15分)
某公司员工的工资计算方法如下:一周内工作时间不超过40小时,按正常工作时间计酬;超出40小时的工作时间部分,按正常工作时间报酬的1.5倍计酬。员工按进公司时间分为新职工和老职工,进公司不少于5年的员工为老职工,5年以下的为新职工。新职工的正常工资为30元/小时,老职工的正常工资为50元/小时。请按该计酬方式计算员工的工资。
- 输入格式:
输入在一行中给出2个正整数,分别为某员工入职年数和周工作时间,其间以空格分隔。 - 输出格式:
在一行输出该员工的周薪,精确到小数点后2位。
输入样例1:
5 40
输出样例1:
2000.00
输入样例2:
3 50
输出样例2:
1650.00
答案:分段计算。
#include <iostream>
#include <cstdio>
using namespace std;
int main() {
int y, w;
cin >> y >> w;
double ans = 0;
int t = y >= 5 ? 50 : 30;
if (w <= 40) ans = w * t;
else ans = 40 * t + (w - 40) * t * 1.5;
printf("%.2lf", ans);
return 0;
}
7-11 分段计算居民水费 (10分)
为鼓励居民节约用水,自来水公司采取按用水量阶梯式计价的办法,居民应交水费y(元)与月用水量x(吨)相关:当x不超过15吨时,y=4x/3;超过后,y=2.5x−17.5。请编写程序实现水费的计算。
- 输入格式:
输入在一行中给出非负实数x。 - 输出格式:
在一行输出应交的水费,精确到小数点后2位。
输入样例1:
12
输出样例1:
16.00
输入样例2:
16
输出样例2:
22.50
答案:分段计算。
#include <iostream>
using namespace std;
int main() {
double x;
cin >> x;
printf("%.2lf", x <= 15 ? 4.0 * x / 3.0 : 2.5 * x - 17.5);
return 0;
}
7-12 两个数的简单计算器 (10分)
本题要求编写一个简单计算器程序,可根据输入的运算符,对2个整数进行加、减、乘、除或求余运算。题目保证输入和输出均不超过整型范围。
- 输入格式:
输入在一行中依次输入操作数1、运算符、操作数2,其间以1个空格分隔。操作数的数据类型为整型,且保证除法和求余的分母非零。 - 输出格式:
当运算符为+、-、*、/、%时,在一行输出相应的运算结果。若输入是非法符号(即除了加、减、乘、除和求余五种运算符以外的其他符号)则输出ERROR。
输入样例1:
-7 / 2
输出样例1:
-3
输入样例2:
3 & 6
输出样例2:
ERROR
答案:
#include <iostream>
using namespace std;
int main() {
int p, q;
char op;
cin >> p >> op >> q;
int a;
switch (op) {
case '+': a = p + q; break;
case '-': a = p - q; break;
case '*': a = p * q; break;
case '/': a = p / q; break;
case '%': a = p % q; break;
default:
cout << "ERROR";
return 0;
}
cout << a;
return 0;
}
7-13 日K蜡烛图 (15分)
股票价格涨跌趋势,常用蜡烛图技术中的K线图来表示,分为按日的日K线、按周的周K线、按月的月K线等。以日K线为例,每天股票价格从开盘到收盘走完一天,对应一根蜡烛小图,要表示四个价格:开盘价格Open(早上刚刚开始开盘买卖成交的第1笔价格)、收盘价格Close(下午收盘时最后一笔成交的价格)、中间的最高价High和最低价Low。
如果Close<Open,表示为“BW-Solid”(即“实心蓝白蜡烛”);如果Close>Open,表示为“R-Hollow”(即“空心红蜡烛”);如果Open等于Close,则为“R-Cross”(即“十字红蜡烛”)。如果Low比Open和Close低,称为“Lower Shadow”(即“有下影线”),如果High比Open和Close高,称为“Upper Shadow”(即“有上影线”)。请编程序,根据给定的四个价格组合,判断当日的蜡烛是一根什么样的蜡烛。
- 输入格式:
输入在一行中给出4个正实数,分别对应Open、High、Low、Close,其间以空格分隔。 - 输出格式:
在一行中输出日K蜡烛的类型。如果有上、下影线,则在类型后加上with 影线类型。如果两种影线都有,则输出with Lower Shadow and Upper Shadow。
输入样例1:
5.110 5.250 5.100 5.105
输出样例1:
BW-Solid with Lower Shadow and Upper Shadow
输入样例2:
5.110 5.110 5.110 5.110
输出样例2:
R-Cross
输入样例3:
5.110 5.125 5.112 5.126
输出样例3:
R-Hollow
答案:先判断蜡烛类型,再判断是否有阴影。
#include <iostream>
using namespace std;
int main() {
double o, h, l, c;
cin >> o >> h >> l >> c;
if (o > c) cout << "BW-Solid";
else if (o < c) cout << "R-Hollow";
else cout << "R-Cross";
if ((l < o && l < c) && (h > o && h > c)) cout << " with Lower Shadow and Upper Shadow";
else if (l < o && l < c) cout << " with Lower Shadow";
else if (h > o && h > c) cout << " with Upper Shadow";
return 0;
}
7-14 求整数段和 (15分)
给定两个整数A和B,输出从A到B的所有整数以及这些数的和。
- 输入格式:
输入在一行中给出2个整数A和B,其中−100≤A≤B≤100,其间以空格分隔。 - 输出格式:
首先顺序输出从A到B的所有整数,每5个数字占一行,每个数字占5个字符宽度,向右对齐。最后在一行中按Sum = X的格式输出全部数字的和X。
输入样例:
-3 8
输出样例:
-3 -2 -1 0 1
2 3 4 5 6
7 8
Sum = 30
答案:照着算:
#include <iostream>
using namespace std;
int main() {
int a, b;
cin >> a >> b;
int num = 0, sum = 0;
int flag = 0;
for (int i = a; i <= b; ++i) {
printf("%5d", i);
sum += i;
num++;
if (num % 5 == 0) { // 每5行换行
printf("\n");
if (i == b) flag = 1; // 输出最后一个数时如果要换行后面就不换行了
}
}
printf(flag ? "" : "\n");
printf("Sum = %d", sum);
return 0;
}
7-15 计算圆周率 (15分)
根据下面关系式,求圆周率的值,直到最后一项的值小于给定阈值。
- 输入格式:
输入在一行中给出小于1的阈值。 - 输出格式:
在一行中输出满足阈值条件的近似圆周率,输出到小数点后6位。
输入样例:
0.01
输出样例:
3.132157
答案:照着公式模拟。
#include <iostream>
using namespace std;
int main() {
double eps, pi = 1, term = 1; // int不够用long long, 再不够用double
double up = 1, down = 3, upNum = 2, downNum = 5;
cin >> eps;
while (term >= eps) {
term = up / down; // 求出每一项的值
pi += term;
up *= upNum; // 累积, 分别求出下一项的分子分母
down *= downNum;
upNum++;
downNum += 2;
}
printf("%.6lf", pi * 2);
return 0;
}
★★ 7-16 求符合给定条件的整数集 (15分)
给定不超过6的正整数A,考虑从A开始的连续4个数字。请输出所有由它们组成的无重复数字的3位数。
- 输入格式:
输入在一行中给出A。 - 输出格式:
输出满足条件的的3位数,要求从小到大,每行6个整数。整数间以空格分隔,但行末不能有多余空格。
输入样例:
2
输出样例:
234 235 243 245 253 254
324 325 342 345 352 354
423 425 432 435 452 453
523 524 532 534 542 543
答案:三层循环暴力搜索。这也可以用排列的方式写A43=4!=24。
#include <iostream>
using namespace std;
int main() {
int A; // <= 6 && > 0
cin >> A;
int arr[10] = {0};
for (int i = A; i < A + 4; ++i) {
arr[i] = 1;
int flag = false; // 控制格式
for (int j = A; j < A + 4; ++j) {
if (arr[j] == 1) continue; // 已经选择该数,则跳过
arr[j] = 1;
for (int k = A; k < A + 4; ++k) {
if (arr[k] == 1) continue; // 已经选择该数,则跳过
arr[k] = 1;
if (flag) printf(" ");
printf("%d%d%d", i, j, k);
flag = true;
arr[k] = 0;
}
arr[j] = 0;
}
arr[i] = 0;
printf("\n");
}
return 0;
}
7-17 爬动的蠕虫 (15分)
一条蠕虫长1寸,在一口深为N寸的井的底部。已知蠕虫每1分钟可以向上爬U寸,但必须休息1分钟才能接着往上爬。在休息的过程中,蠕虫又下滑了D寸。就这样,上爬和下滑重复进行。请问,蠕虫需要多长时间才能爬出井?
这里要求不足1分钟按1分钟计,并且假定只要在某次上爬过程中蠕虫的头部到达了井的顶部,那么蠕虫就完成任务了。初始时,蠕虫是趴在井底的(即高度为0)。
- 输入格式:
输入在一行中顺序给出3个正整数N、U、D,其中D<U,N不超过100。 - 输出格式:
在一行中输出蠕虫爬出井的时间,以分钟为单位。
输入样例:
12 3 1
输出样例:
11
答案:模拟题,计算时间,数分钟即可。
#include <iostream>
using namespace std;
int main() {
int n, u, d;
cin >> n >> u >> d;
int min = 0, dist = 0;
while (1) {
dist += u;
++min;
if (dist >= n) break;
dist -= d;
++min;
}
cout << min;
return 0;
}
/*
minutes distance
1 3
2 2
3 5
4 4
5 7
6 6
7 9
8 8
9 11
10 10
11 13
*/
★★ 7-18 二分法求多项式单根 (20分)
二分法求函数根的原理为:如果连续函数f(x)在区间[a,b]的两个端点取值异号,即f(a)f(b)<0,则它在这个区间内至少存在1个根r,即f(r)=0
。
二分法的步骤为:
检查区间长度,如果小于给定阈值,则停止,输出区间中点(a+b)/2;否则
如果f(a)f(b)<0,则计算中点的值f((a+b)/2);
如果f((a+b)/2)正好为0,则(a+b)/2就是要求的根;否则
如果f((a+b)/2)与f(a)同号,则说明根在区间[(a+b)/2,b],令a=(a+b)/2,重复循环;
如果f((a+b)/2)与f(b)同号,则说明根在区间[a,(a+b)/2],令b=(a+b)/2,重复循环。
本题目要求编写程序,计算给定3阶多项式f(x)=a3x3+a2x2+a1x+a0在给定区间[a,b]内的根。
- 输入格式:
输入在第1行中顺序给出多项式的4个系数a3、a2、a1、a0,在第2行中顺序给出区间端点a和b。题目保证多项式在给定区间内存在唯一单根。 - 输出格式:
在一行中输出该多项式在该区间内的根,精确到小数点后2位。
输入样例:
3 -1 -3 1
-0.5 0.5
输出样例:
0.33
答案:这里要注意的是,题目的描述不太完整:
检查区间长度,如果小于给定阈值,则停止,输出区间中点(a+b)/2;否则
如果f(a)f(b)<0,则计算中点的值f((a+b)/2);
如果f(a)或f(b)正好为0,则输出a或者b作为要求的根;
如果f((a+b)/2)正好为0,则(a+b)/2就是要求的根;否则
如果f((a+b)/2)与f(a)同号,则说明根在区间[(a+b)/2,b],令a=(a+b)/2,重复循环;
如果f((a+b)/2)与f(b)同号,则说明根在区间[a,(a+b)/2],令b=(a+b)/2,重复循环。
#include <iostream>
#include <cmath>
using namespace std;
double a3, a2, a1, a0;
double f(double x) {
return a3 * x * x * x + a2 * x * x + a1 * x + a0;
}
// 题目的二分法描述有点问题
int main() {
cin >> a3 >> a2 >> a1 >> a0;
double a, b;
cin >> a >> b;
double x;
while ((b - a) >= 0.01) {
double fa = f(a), fb = f(b);
if (fa * fb < 0) x = (a + b) / 2;
else if (fa == 0.0 || fb == 0.0) {
printf("%.2lf", fa == 0.0 ? a : b);
return 0;
}
double v = f(x);
if (v == 0.0) { // (a+b)/2就是要求的根
printf("%.2lf", x);
return 0;
}
else if (v * fa > 0) a = x;
else if (v * fb > 0) b = x;
}
printf("%.2lf", (a + b) / 2.0); // 输出区间中点(a+b)/2
return 0;
}
★★ 7-19 支票面额 (15分)
一个采购员去银行兑换一张y元f分的支票,结果出纳员错给了f元y分。采购员用去了n分之后才发觉有错,于是清点了余额尚有2y元2f分,问该支票面额是多少?
- 输入格式:
输入在一行中给出小于100的正整数n。 - 输出格式:
在一行中按格式y.f输出该支票的原始面额。如果无解,则输出No Solution。
输入样例1:
23
输出样例1:
25.51
输入样例2:
22
输出样例2:
No Solution
答案:要注意到题目中的隐含条件,y和f都不能大于100,n也<100,然后按照程序中的注释得到199y-98f+n=0
,在相应的空间中搜索答案即可,最后需要注意的是y和f都不能为0,不然哪有正整数n?
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
struct yuan {
int y, f, n;
};
int main() {
int n;
cin >> n;
// y元f分 f<100 // f元y分 y<100 n<100
// f元y分-n分=2y元2f分
// 199y-98f+n=0
vector<yuan> vi(101);
for (int i = 0; i < 100; ++i) {
for (int j = 0; j < 100; ++j) {
int ans = 199 * i - 98 * j;
if (ans < 0 && ans > -100)
vi[-ans] = yuan{i, j, -ans};
}
}
if (vi[n].y != 0 || vi[n].f != 0) printf("%d.%d", vi[n].y, vi[n].f); // 算出来的y和f不为0.0
else printf("No Solution");
return 0;
}
7-20 打印九九口诀表 (15分)
下面是一个完整的下三角九九口诀表:
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
本题要求对任意给定的一位正整数N,输出从11到NN的部分口诀表。
- 输入格式:
输入在一行中给出一个正整数N(1≤N≤9)。 - 输出格式:
输出下三角N*N部分口诀表,其中等号右边数字占4位、左对齐。
输入样例:
4
输出样例:
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
答案:打表即可。
#include <iostream>
#include <string>
using namespace std;
string s[] = {
"1*1=1 ",
"1*2=2 2*2=4 ",
"1*3=3 2*3=6 3*3=9 ",
"1*4=4 2*4=8 3*4=12 4*4=16 ",
"1*5=5 2*5=10 3*5=15 4*5=20 5*5=25 ",
"1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36 ",
"1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49 ",
"1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64 ",
"1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81 "
};
// 等号后面有4位,其中数字左对齐,剩余空间以空格填充
int main() {
int n;
cin >> n;
for (int i = 0; i < n - 1; ++i)
cout << s[i] << endl;
cout << s[n - 1];
return 0;
}
7-21 求特殊方程的正整数解 (15分)
本题要求对任意给定的正整数N,求方程X2+Y2=N的全部正整数解。
- 输入格式:
输入在一行中给出正整数N(≤10000)。 - 输出格式:
输出方程X2+Y2=N的全部正整数解,其中X≤Y。每组解占1行,两数字间以1空格分隔,按X的递增顺序输出。如果没有解,则输出No Solution。
输入样例1:
884
输出样例1:
10 28
20 22
输入样例2:
11
输出样例2:
No Solution
答案:X和Y都小于等于100,直接在数据中进行搜索即可。
#include <iostream>
#include <cmath>
using namespace std;
int main() {
int n;
cin >> n;
int sqr = sqrt(n);
bool flag = true;
for (int x = 1; x <= sqr; ++x) {
for (int y = 1; y <= sqr; ++y) {
if (x <= y && x * x + y * y == n) {
cout << x << " " << y << endl;
flag = false;
}
}
}
if (flag) cout << "No Solution";
return 0;
}
★★ 7-22 龟兔赛跑 (20分)
乌龟与兔子进行赛跑,跑场是一个矩型跑道,跑道边可以随地进行休息。乌龟每分钟可以前进3米,兔子每分钟前进9米;兔子嫌乌龟跑得慢,觉得肯定能跑赢乌龟,于是,每跑10分钟回头看一下乌龟,若发现自己超过乌龟,就在路边休息,每次休息30分钟,否则继续跑10分钟;而乌龟非常努力,一直跑,不休息。假定乌龟与兔子在同一起点同一时刻开始起跑,请问T分钟后乌龟和兔子谁跑得快?
- 输入格式:
输入在一行中给出比赛时间T(分钟)。 - 输出格式:
在一行中输出比赛的结果:乌龟赢输出@@,兔子赢输出_,平局则输出--;后跟1空格,再输出胜利者跑完的距离。
输入样例:
242
输出样例:
@_@ 726
答案:关键在于兔子什么时候休息,兔子休息时会不会看乌龟等细节处理,这里用了一个flag,为true时兔子奔跑,并每隔十分钟观察一下乌龟;为false时休息。
#include <iostream>
using namespace std;
/* t w
1 9 3 兔子奔跑中赢,乌龟奔跑中输
10 90 30
... 兔子休息中赢,乌龟奔跑中输
30 90 90 兔子休息中平局,乌龟奔跑中平局
... 兔子休息中输,乌龟奔跑中赢
40 90 120
... 兔子奔跑中输,乌龟奔跑中赢
45 135 135 兔子乌龟奔跑中平局
... 兔子奔跑中赢,乌龟奔跑中输
50 180 150
... 兔子休息中赢,乌龟奔跑中输
60 180 180 兔子休息中平局,乌龟奔跑中平局
*/
int main() {
int T;
cin >> T;
int tdis = 0, wdis = 0; // 兔子跑的距离,乌龟跑的距离
int tflag = true; // 兔子是否休息
int tmin = 0; // 临时计时器, 记录上一个时刻
for (int i = 1; i <= T; ++i) { // 过去了一分钟
wdis += 3;
if (tflag) tdis += 9;
if (tflag && i % 10 == 0 && tdis > wdis) { // 在奔跑中每10分钟比较一次距离
tflag = false; // 超过的话兔子休息
tmin = i; // 记录这个时刻点
}
if (i - tmin == 30) tflag = true; // 每次休息30分钟
}
if (tdis > wdis) printf("^_^ %d", tdis);
else if (wdis > tdis) printf("@_@ %d", wdis);
else printf("-_- %d", tdis); // 后跟1空格,再输出胜利者跑完的距离 // 艹, 平局也要输出距离
return 0;
}
★★★ 7-23 币值转换 (20分) 中文习惯读数字
输入一个整数(位数不超过9位)代表一个人民币值(单位为元),请转换成财务要求的大写中文格式。如23108元,转换后变成“贰万叁仟壹百零捌”元。为了简化输出,用小写英文字母a-j顺序代表大写数字0-9,用S、B、Q、W、Y分别代表拾、百、仟、万、亿。于是23108元应被转换输出为“cWdQbBai”元。
- 输入格式:
输入在一行中给出一个不超过9位的非负整数。 - 输出格式:
在一行中输出转换后的结果。注意“零”的用法必须符合中文习惯。
输入样例1:
813227345
输出样例1:
iYbQdBcScWhQdBeSf
输入样例2:
6900
输出样例2:
gQjB
#include <iostream>
#include <string>
using namespace std;
// a 0; b 1; c 2; d 3; e 4; f 5; g 6; h 7; i 8; j 9
int main() {
string s;
cin >> s;
if (s.size() == 1 && s[0] == '0') {
cout << 'a';
return 0;
}
string ans;
char c[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'};
for (int i = s.size() - 1; i >= 0; --i) {
int j = s.size() - i - 1, n = s[j] - '0';
if (n == 0) {
int endPos, flag = false;
switch (i) { // i为数位
case 8: endPos = 0; break;
case 7:
case 6:
case 5:
case 4: endPos = s.size() - 1 - 4; break;
case 3:
case 2:
case 1:
case 0: endPos = s.size() - 1; break;
}
for (int k = j + 1; k <= endPos; ++k) {
if (s[k] != '0') {
flag = true;
break;
}
}
if (flag && ans[ans.size() - 1] != 'a') ans += 'a';
if (i == 4 && s.size() <= 8) ans += 'W';
continue;
} else ans += c[n];
if (i == 8) {
ans += 'Y';
} else if (i == 7 || i == 3) {
ans += 'Q';
} else if (i == 6 || i == 2) {
ans += 'B';
} else if (i == 5 || i == 1) {
ans += 'S';
} else if (i == 4)
ans += 'W';
}
cout << ans;
return 0;
}
7-24 约分最简分式 (15分)
分数可以表示为分子/分母的形式。编写一个程序,要求用户输入一个分数,然后将其约分为最简分式。最简分式是指分子和分母不具有可以约分的成分了。如6/12可以被约分为1/2。当分子大于分母时,不需要表达为整数又分数的形式,即11/8还是11/8;而当分子分母相等时,仍然表达为1/1的分数形式。
- 输入格式:
输入在一行中给出一个分数,分子和分母中间以斜杠/分隔,如:12/34表示34分之12。分子和分母都是正整数(不包含0,如果不清楚正整数的定义的话)。
提示:在scanf的格式字符串中加入/,让scanf来处理这个斜杠。 - 输出格式:
在一行中输出这个分数对应的最简分式,格式与输入的相同,即采用分子/分母的形式表示分数。如 5/6表示6分之5。
输入样例:
66/120
输出样例:
11/20
答案:直接算。
#include <iostream>
using namespace std;
using ll = long long;
ll gcd(ll a, ll b) {
return !b ? a : gcd(b, a % b);
}
int main() {
ll a, b;
scanf("%lld/%lld", &a, &b);
ll c = gcd(a, b);
printf("%lld/%lld", a / c, b / c);
return 0;
}
7-25 念数字 (15分)
输入一个整数,输出每个数字对应的拼音。当整数为负数时,先输出fu字。十个数字对应的拼音如下:
0: ling
1: yi
2: er
3: san
4: si
5: wu
6: liu
7: qi
8: ba
9: jiu
输入格式:
输入在一行中给出一个整数,如:1234。
提示:整数包括负数、零和正数。
输出格式:
在一行中输出这个整数对应的拼音,每个数字的拼音之间用空格分开,行末没有最后的空格。如 yi er san si。
输入样例:
-600
输出样例:
fu liu ling ling
答案:这里是很简单的念数字。
#include <iostream>
#include <map>
#include <string>
using namespace std;
map<char, string> m = {
{'-', "fu"}, {'0', "ling"}, {'1', "yi"}, {'2', "er"}, {'3', "san"}, {'4', "si"},
{'5', "wu"}, {'6', "liu"}, {'7', "qi"}, {'8', "ba"}, {'9', "jiu"}
};
int main() {
string s;
cin >> s;
for (int i = 0; i < s.size(); ++i) {
if (i != 0) cout << ' ';
cout << m[s[i]];
}
return 0;
}
★★ 7-26 单词长度 (15分)
你的程序要读入一行文本,其中以空格分隔为若干个单词,以.结束。你要输出每个单词的长度。这里的单词与语言无关,可以包括各种符号,比如it’s算一个单词,长度为4。注意,行中可能出现连续的空格;最后的.不计算在内。
- 输入格式:
输入在一行中给出一行文本,以.结束
提示:用scanf("%c",…);来读入一个字符,直到读到.为止。 - 输出格式:
在一行中输出这行文本对应的单词的长度,每个长度之间以空格隔开,行末没有最后的空格。
输入样例:
It's great to see you here.
输出样例:
4 5 2 3 3 4
答案:这一题对空格的判断很严格,要通过以下的测试才行,还有输出格式也要注意。
hello world .
.
hello world .
.
5 5
(此组什么也不能输出)
5 5
(此组什么也不能输出)
#include <iostream>
using namespace std;
int main() {
char c, prec = ' ';
int len = 0;
bool flag = false;
while (scanf("%c", &c)) {
if (c == '.') {
if (prec != ' ') {
if (flag) cout << " ";
cout << len << endl; //最后一个单词长度
}
break;
} else if (c == ' ' && prec == ' ') continue;
else if (c == ' ' && prec != ' ') {
if (flag) cout << " ";
cout << len;
flag = true;
len = 0;
}
else if (c != ' ') len++;
prec = c;
}
return 0;
}
7-27 冒泡法排序 (20分)
将N个整数按从小到大排序的冒泡排序法是这样工作的:从头到尾比较相邻两个元素,如果前面的元素大于其紧随的后面元素,则交换它们。通过一遍扫描,则最后一个元素必定是最大的元素。然后用同样的方法对前N−1个元素进行第二遍扫描。依此类推,最后只需处理两个元素,就完成了对N个数的排序。
本题要求对任意给定的K(<N),输出扫描完第K遍后的中间结果数列。
- 输入格式:
输入在第1行中给出N和K(1≤K<N≤100),在第2行中给出N个待排序的整数,数字间以空格分隔。 - 输出格式:
在一行中输出冒泡排序法扫描完第K遍后的中间结果数列,数字间以空格分隔,但末尾不得有多余空格。
输入样例:
6 2
2 3 5 1 6 4
输出样例:
2 1 3 4 5 6
答案:只进行K次排序过程。
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int n, k;
cin >> n >> k;
int arr[n];
for (int i = 0; i < n; ++i) cin >> arr[i];
for (int i = n - 1; i > n - 1 - k; --i) {
int flag = true; // 是否退出的标志
for (int j = 0; j < i; ++j) {
if (arr[j] > arr[j + 1]) {
swap(arr[j], arr[j + 1]);
flag = false;
}
}
if (flag) break;
}
for (int i = 0; i < n - 1; ++i) cout << arr[i] << " ";
cout << arr[n - 1];
return 0;
}
【约瑟夫环】7-28 猴子选大王 (20分)
【PTA】【约瑟夫环】基础编程题目集 编程题部分 7-28 猴子选大王 (20分)
★ 7-29 删除字符串中的子串 (20分)
输入2个字符串S1和S2,要求删除字符串S1中出现的所有子串S2,即结果字符串中不能包含S2。
- 输入格式:
输入在2行中分别给出不超过80个字符长度的、以回车结束的2个非空字符串,对应S1和S2。 - 输出格式:
在一行中输出删除字符串S1中出现的所有子串S2后的结果字符串。
输入样例:
Tomcat is a male ccatat
cat
输出样例:
Tom is a male
答案:可以进行字符串的暴力匹配,自己写;也可以用string的find函数,不过后面的简单太多了。
#include <iostream>
using namespace std;
// int bf(const string &s, const string &t) {
// int i = 0, j = 0;
// while (i < s.size() && j < t.size()) {
// if (s[i] == t[j]) {
// ++i;
// ++j;
// } else {
// i = i - j + 1;
// j = 0;
// }
// }
// if (j >= t.size()) return i - t.size();
// else return -1;
// }
int main() {
string s, t;
getline(cin, s);
getline(cin, t);
int index;
// while ((index = bf(s, t)) != -1) {
// s.erase(index, t.size());
// }
while ((index = s.find(t)) != s.npos) {
s.erase(index, t.size());
}
cout << s;
return 0;
}
7-30 字符串的冒泡排序 (20分)
我们已经知道了将N个整数按从小到大排序的冒泡排序法。本题要求将此方法用于字符串序列,并对任意给定的K(<N),输出扫描完第K遍后的中间结果序列。
- 输入格式:
输入在第1行中给出N和K(1≤K<N≤100),此后N行,每行包含一个长度不超过10的、仅由小写英文字母组成的非空字符串。 - 输出格式:
输出冒泡排序法扫描完第K遍后的中间结果序列,每行包含一个字符串。
输入样例:
6 2
best
cat
east
a
free
day
输出样例:
best
a
cat
day
east
free
答案:string间的比较就是按照字典序的,这样会简单很多。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int n, k;
cin >> n >> k;
vector<string> vi;
string t;
for (int i = 0; i < n; ++i) {
cin >> t;
vi.push_back(t);
}
for (int i = n - 1; i > n - 1 - k; --i)
for (int j = 0; j < i; ++j)
if (vi[j] > vi[j + 1])
swap(vi[j], vi[j + 1]);
for (int i = 0; i < vi.size(); ++i) cout << vi[i] << endl;
return 0;
}
7-31 字符串循环左移 (20分)
输入一个字符串和一个非负整数N,要求将字符串循环左移N次。
- 输入格式:
输入在第1行中给出一个不超过100个字符长度的、以回车结束的非空字符串;第2行给出非负整数N。 - 输出格式:
在一行中输出循环左移N次后的字符串。
输入样例:
Hello World!
2
输出样例:
llo World!He
答案:老套路了。
#include <iostream>
#include <string>
using namespace std;
void reverse(string &s, int lo, int hi) {
while (lo < hi) {
char t = s[lo];
s[lo] = s[hi];
s[hi] = t;
lo++;
hi--;
}
}
int main() {
string s;
int k;
getline(cin, s);
cin >> k;
k %= s.size(); // k大于字符串长度
reverse(s, 0, k - 1);
reverse(s, k, s.size() - 1);
reverse(s, 0, s.size() - 1);
cout << s;
return 0;
}
7-32 说反话-加强版 (20分)
给定一句英语,要求你编写程序,将句中所有单词的顺序颠倒输出。
- 输入格式:
测试输入包含一个测试用例,在一行内给出总长度不超过500 000的字符串。字符串由若干单词和若干空格组成,其中单词是由英文字母(大小写有区分)组成的字符串,单词之间用若干个空格分开。 - 输出格式:
每个测试用例的输出占一行,输出倒序后的句子,并且保证单词间只有1个空格。
输入样例:
Hello World Here I Come
输出样例:
Come I Here World Hello
答案:记录每个单词,反向输出。
#include<iostream>
#include<vector>
#include<string>
using namespace std;
int main() {
string s;
vector<string> v;
while (cin >> s) v.push_back(s);
for (int i = v.size() - 1; i > 0; --i) cout << v[i] << " ";
if (v.size() > 0) cout << v[0];
return 0;
}
7-33 有理数加法 (15分)
本题要求编写程序,计算两个有理数的和。
- 输入格式:
输入在一行中按照a1/b1 a2/b2的格式给出两个分数形式的有理数,其中分子和分母全是整形范围内的正整数。 - 输出格式:
在一行中按照a/b的格式输出两个有理数的和。注意必须是该有理数的最简分数形式,若分母为1,则只输出分子。
输入样例1:
1/3 1/6
输出样例1:
1/2
输入样例2:
4/3 2/3
输出样例2:
2
答案:直接按照分数相加的方法计算即可,注意化简。
#include <iostream>
using namespace std;
using ll = long long;
ll gcd(ll a, ll b) {
return !b ? a : gcd(b, a % b);
}
int main() {
ll a, b, c, d;
scanf("%lld/%lld %lld/%lld", &a, &b, &c, &d);
ll down = b * d, up = a * d + c * b;
ll g = gcd(up, down);
if (down / g != 1) printf("%lld/%lld", up / g, down / g);
else printf("%lld", up / g);
return 0;
}
7-34 通讯录的录入与显示 (10分)
通讯录中的一条记录包含下述基本信息:朋友的姓名、出生日期、性别、固定电话号码、移动电话号码。 本题要求编写程序,录入N条记录,并且根据要求显示任意某条记录。
-
输入格式:
输入在第一行给出正整数N(≤10);随后N行,每行按照格式姓名 生日 性别 固话 手机给出一条记录。其中姓名是不超过10个字符、不包含空格的非空字符串;生日按yyyy/mm/dd的格式给出年月日;性别用M表示“男”、F表示“女”;固话和手机均为不超过15位的连续数字,前面有可能出现+。在通讯录记录输入完成后,最后一行给出正整数K,并且随后给出K个整数,表示要查询的记录编号(从0到N−1顺序编号)。数字间以空格分隔。
-
输出格式:
对每一条要查询的记录编号,在一行中按照姓名 固话 手机 性别 生日的格式输出该记录。若要查询的记录不存在,则输出Not Found。
输入样例:
3
Chris 1984/03/10 F +86181779452 13707010007
LaoLao 1967/11/30 F 057187951100 +8618618623333
QiaoLin 1980/01/01 M 84172333 10086
2 1 7
输出样例:
LaoLao 057187951100 +8618618623333 F 1967/11/30
Not Found
答案:简单的查找。
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct note {
string name;
string solid, phone;
char c;
int y, m, d;
note(string &na, int _y, int _m, int _d, char _c, string &s, string &p)
:name(na), solid(s), phone(p), c(_c), y(_y), m(_m), d(_d) { }
};
int main() {
int n;
cin >> n;
vector<note> vi;
string na, s, p;
char c;
int y, m, d;
while (n--) {
cin >> na;
scanf("%d/%d/%d", &y, &m, &d);
cin >> c >> s >> p;
vi.emplace_back(note(na, y, m, d, c, s, p));
}
int k, i;
cin >> k;
while (k--) {
cin >> i;
if (i >= vi.size()) cout << "Not Found\n";
else {
cout << vi[i].name << " ";
cout << vi[i].solid << " " << vi[i].phone;
printf(" %c %04d/%02d/%02d\n", vi[i].c, vi[i].y, vi[i].m, vi[i].d);
}
}
return 0;
}
【有理数模板】7-35 有理数均值 (20分)
本题要求编写程序,计算N个有理数的平均值。
- 输入格式:
输入第一行给出正整数N(≤100);第二行中按照a1/b1 a2/b2 …的格式给出N个分数形式的有理数,其中分子和分母全是整形范围内的整数;如果是负数,则负号一定出现在最前面。 - 输出格式:
在一行中按照a/b的格式输出N个有理数的平均值。注意必须是该有理数的最简分数形式,若分母为1,则只输出分子。
输入样例1:
4
1/2 1/6 3/6 -5/10
输出样例1:
1/6
输入样例2:
2
4/3 2/3
输出样例2:
1
答案:常规的有理数模板,化简和分数加法,这里要注意的是,每一次加法后都必须进行化简,不然可能出现“浮点错误”。
#include <iostream>
using namespace std;
using ll = long long;
struct frac {
ll u, d;
frac() { }
frac(ll up, ll down) : u(up), d(down) { }
};
ll gcd(ll a, ll b) {
return !b ? a : gcd(b, a % b);
}
void add(frac &a, const frac &b) {
ll d = a.d * b.d;
ll u = a.u * b.d + b.u * a.d;
a.u = u, a.d = d;
}
void reduce(frac &a) {
ll g = gcd(a.u, a.d);
a.u /= g, a.d /= g;
}
int main() {
int n;
cin >> n;
frac ans, temp;
scanf("%lld/%lld", &ans.u, &ans.d);
for (int i = 1; i < n; ++i) {
scanf("%lld/%lld", &temp.u, &temp.d);
add(ans, temp);
reduce(ans);
}
ans.d *= n;
reduce(ans);
if (ans.d != 1) cout << ans.u << "/" << ans.d;
else cout << ans.u;
return 0;
}
【复数运算】7-36 复数四则运算 (15分)
本题要求编写程序,计算2个复数的和、差、积、商。
输入格式:
输入在一行中按照a1 b1 a2 b2的格式给出2个复数C1=a1+b1i和C2=a2+b2i的实部和虚部。题目保证C2不为0。
输出格式:
分别在4行中按照(a1+b1i) 运算符 (a2+b2i) = 结果的格式顺序输出2个复数的和、差、积、商,数字精确到小数点后1位。如果结果的实部或者虚部为0,则不输出。如果结果为0,则输出0.0。
输入样例1:
2 3.08 -2.04 5.06
输出样例1:
(2.0+3.1i) + (-2.0+5.1i) = 8.1i
(2.0+3.1i) - (-2.0+5.1i) = 4.0-2.0i
(2.0+3.1i) * (-2.0+5.1i) = -19.7+3.8i
(2.0+3.1i) / (-2.0+5.1i) = 0.4-0.6i
输入样例2:
1 1 -1 -1.01
输出样例2:
(1.0+1.0i) + (-1.0-1.0i) = 0.0
(1.0+1.0i) - (-1.0-1.0i) = 2.0+2.0i
(1.0+1.0i) * (-1.0-1.0i) = -2.0i
(1.0+1.0i) / (-1.0-1.0i) = -1.0
答案:复数运算,除法运算要小心。
#include <iostream>
#include <cmath>
using namespace std;
void print(double a, double b) {
printf("%.1lf", a);
if (b >= 0.0) printf("+%.1lfi", b);
else printf("%.1lfi", b);
}
void printSample(double a, double b) {
cout << "(";
print(a, b);
cout << ")";
}
void myRound(double &a) {
a = round(a * 10.0) / 10.0;
}
void printResult(double a, double b) {
myRound(a), myRound(b);
if (a == 0.0 && b == 0.0) printf("0.0");
else if (a == 0.0) printf("%.1lfi", b);
else if (b == 0.0) printf("%.1lf", a);
else print(a, b);
}
int main() {
double a, b, c, d, ra, rb; // c1 c2
cin >> a >> b >> c >> d;
// 先用原来的数加减乘除,打印的时候才保留一位小数
char ch[4] = {'+', '-', '*', '/'};
for (int i = 0; i < 4; ++i) {
printSample(a, b);
printf(" %c ", ch[i]);
switch (ch[i]) {
case '+': ra = a + c, rb = b + d; break;
case '-': ra = a - c, rb = b - d; break;
case '*': ra = a * c - b * d, rb = a * d + c * b; break;
case '/': ra = (a * c + b * d) / (c * c + d * d),
rb = (b * c - a * d) / (c * c + d * d); break;
}
printSample(c, d);
printf(" = ");
printResult(ra, rb); // 针对结果的打印
cout << endl;
}
return 0;
}
★★★ 7-37 整数分解为若干项之和 (20分)
将一个正整数N分解成几个正整数相加,可以有多种分解方法,例如7=6+1,7=5+2,7=5+1+1,…。编程求出正整数N的所有整数分解式子。
输入格式:每个输入包含一个测试用例,即正整数N (0<N≤30)。
输出格式:按递增顺序输出N的所有整数分解式子。递增顺序是指:对于两个分解序列N1={n1,n2,⋯}和N2={m1,m2,⋯},若存在i使得n1=m1,⋯,ni=mi,但是ni+1<mi+1,则N1序列必定在N2序列之前输出。每个式子由小到大相加,式子间用分号隔开,且每输出4个式子后换行。
输入样例:
7
输出样例:
7=1+1+1+1+1+1+1;7=1+1+1+1+1+2;7=1+1+1+1+3;7=1+1+1+2+2
7=1+1+1+4;7=1+1+2+3;7=1+1+5;7=1+2+2+2
7=1+2+4;7=1+3+3;7=1+6;7=2+2+3
7=2+5;7=3+4;7=7
答案:通过剪枝+DFS,来得到所有的解。
#include<iostream>
#include<vector>
using namespace std;
vector<vector<int>> vi;
int n;
void dfs(int sum, vector<int> &v) {
if (sum == n) {
vi.push_back(v);
return;
}
for (int i = 1; i <= n; ++i) {
if (sum + i > n) return; // 剪枝
if (v.size() > 0 && v[v.size() - 1] > i) continue;
v.push_back(i);
dfs(sum + i, v);
v.pop_back();
}
}
void print(int i) { // 打印结果序列vi中的下标为i的序列
cout << n << "=";
int l = vi[i].size();
for (int j = 0; j < l - 1; ++j)
cout << vi[i][j] << "+";
cout << vi[i][l - 1];
}
int main() {
cin >> n;
vector<int> t;
dfs(0, t);
// sort(vi.begin(), vi.end()); // dfs时已经按照题目要求的顺序求序列
for (int i = 0; i < vi.size(); ++i) {
print(i);
if ((i + 1) % 4 == 0 || i == vi.size() - 1) printf("\n");
else printf(";");
}
return 0;
}
★★★ 7-38 数列求和-加强版 (20分)
给定某数字A(1≤A≤9)以及非负整数N(0≤N≤100000),求数列之和S=A+AA+AAA+⋯+AA⋯A(N个A)。例如A=1, N=3时,S=1+11+111=123。
输入格式:输入数字A与非负整数N。
输出格式:输出其N项数列之和S的值。
输入样例:
1 3
输出样例:
123
答案:这题我没有用大整数,而是通过规律计算,直接拼凑字符串得到结果。从最低位算起,最低位无疑是A*N,保留余数,进位参与次低位的运算。
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
int main() {
int a, n;
cin >> a >> n;
if (n == 0) {
cout << 0;
return 0;
}
string s = "";
int r = 0, t;
for (int i = n; i >= 1; --i) {
t = i * a + r;
r = t / 10;
s += (t % 10 + '0');
}
while (r) {
t = r % 10;
s += (t + '0');
r /= 10;
}
reverse(s.begin(), s.end());
cout << s;
return 0;
}