云计算百科
云计算领域专业知识百科平台

HAUE软件学院OJ题解汇总_第2篇_1050-1099

河南工程学院软件学院 OJ 题解(第 2 篇 / 共 4 篇):题号 1050–1099

题库:http://oj.software.haue.edu.cn/  语言:C++(g++ -std=c++14 -O2)
覆盖题号:1050–1099(本篇 50 题) 内容:第4章 循环结构
全套共 4 篇:1000–1049 / 1050–1099 / 1100–1149 / 1150–1199

⚠️ 本篇含 1095:该题被管理员停用,无题面,代码为占位。

验证方式:每题源码都在本机用 g++ 编译通过,并跑题面样例与输出逐字符比对;
比对基准取自 OJ 原始页面(保留样例的行末空格与空行),按 HUSTOJ 默认宽松判题规则判定。
全部 200 题中 199 题已向 OJ 真机提交验证并 AC:
1095 被管理员停用无法验证;1198 因题面歧义通过 81%(详见该题说明)。
真机测试发现并修复 4 处:1083 输出对齐、1057 用券组合取最小、1165 差值符号、1199 降档发放。

提交方法:打开题目页 → 提交 → 语言选 C++ → 粘贴本文档中对应题的代码。


快速索引(本篇 50 题)

题号题目思路复杂度
1050 加班费 按 160 小时分段:未超出部分 10 元/时,超出部分 30 元/时(3 倍工资)。 O(1)
1051 某年某月的天数 月份天数打表,仅 2 月在闰年时改为 29;闰年判 `(y%4==0&&y%100!=0)
1052 蚂蚁的位置 比较 x²+y² 与 r²=20.25,加 1e-6 容差后输出 in/on/out,避免临界点被浮点误差带偏。 O(1)
1053 吃水果 switch 映射 A/B/C/D → Apple/Banana/Cherry/Durian,大写小写同映射,其余 → Mango。 O(1)
1054 进制转换 按字符串读入二进制数(保留前导 0),逐位 v=v*2+(c-'0'),long long 承接 31 位。 O(位数)
1055 整数对数 printf("%4d%8.4f") —— 整数占 4 列、对数(自然对数 ln)占 8 列右对齐,占位列不能省。 O(n-m+1)
1056 整数数字 按字符串逐位输出每个数字,且每位数字后都跟一个空格。 O(位数)
1057 优惠支付 满减券/打折券可同用或只用一种,「最少支付」= 4 种方案(都不用 / 只打折 / 只满减 / 先折后减)取最小,每种金额钳 0 后输出 %.2f。真机验证:只算「先折后减」会挂数据(AC:95%),取 min 后 AC。 O(商品行数)
1058 最不高兴 7 天求和,只有和数 >8 才算不高兴;严格比较保证并列时取最早的一天。 O(1)
1059 画矩形 实心每行 w 个字符;空心首末行 w 个字符、中间行两端各 1 个字符、中间留 w-2 个空格。 O(h·w)
1060 角谷猜想 角谷猜想:奇数 n=n*3+1、偶数 n=n/2,每步输出算式,最后输出 End。 O(步数)
1061 公式求值 e=1+Σ1/i!,用 term/=i 递推避免直接算阶乘,输出 10 位小数。 O(n)
1062 整数累加 等差数列求和 (m+n)*(n-m+1)/2,用公式替代循环并防溢出。 O(1)
1063 多实例测试 多实例:while(scanf(…)==2) 读到 EOF,每组输出一行 a+b。 O(组数)
1064 最小整数 找最小 i 使 i(i+1)/2 ≥ n;用 sqrt 估算后双向微调,做到 O(1) 而非累加。 O(1)
1065 质数判断 n≥2 才可能质数;试除到 sqrt(n),写成 i<=n/i 防止 i*i 溢出。 O(√n)
1066 前n项和 第 i 项 = (-1)^(i-1)·i/(2i-1),累加后输出 3 位小数。 O(n)
1067 质数判断(break) 与 1065 同解,显式用 break 在找到因子时提前跳出,满足题目对 break 的要求。 O(√n)
1068 整数整除 枚举 a…b 输出所有不能被 3 整除的数,用 first 标志控制空格以保证行末无空格。 O(b-a)
1069 m钱买m只鸡 消元得 7x+4y=m,x 从 0 枚举,首个可行解即公鸡最少的解;输出顺序为 公鸡 母鸡 小鸡。 O(m)
1070 质数数目 区间筛:先用试除筛出 √b 内的质数,再按段筛 [a,b] 并计数;注意 1 不是质数。 O(√b+(b-a))
1071 m钱买m只鸡(无解输出“No answer”) 同 1069 的消元枚举,无解时输出半角 No answer。 O(m)
1072 整数的位数(while实现) while(n>0){cnt++;n/=10;} 逐位去掉末位计数,用 long long。 O(位数)
1073 数字反转 取绝对值后算术反转再补符号,末尾的 0 自然消失(1200→21)。 O(位数)
1074 礼物数量 第 n 个不含数字 4 的正整数:把 n 的各位当作 9 进制加权,数字 >4 时减 1。 O(位数)
1075 分解质因子 从小到大试除分解质因子,用 * 连接输出(按题面样例不加 n= 前缀)。 O(√n)
1076 数列累加 term=term*10+a 生成 a, aa, aaa… 并累加,用 long long 防溢出。 O(n·位数)
1077 零花钱奖励 m 是百元钞票张数(总额 100m);逐天模拟,连续攒够 k 天即 +10 元并重置计数。 O(天数)
1078 阶乘最高位 阶乘首位:用 long double 累加对数,首位 = ⌊10^小数部分⌋,避免直接算阶乘。 O(n)
1079 小车的位置 方向数组 {北,西,南,东},先按 (t-prev)*10 行驶再执行转向/停止命令。 O(命令数)
1080 乘积反转 a*b 后逐位反转拼接 r=r*10+n%10,前导零自然丢弃。 O(位数)
1081 两个数的最大公约数 辗转相除法(欧几里得算法)求最大公约数。 O(log min(a,b))
1082 两个数的最小公倍数 a/gcd*b —— 先除后乘,避免 a*b 溢出。 O(log min(a,b))
1083 九九乘法表(一) 第 i 行输出 j=1…i,格式 i*j=i*j,项间单空格、行末无空格。注意:题面样例里的宽对齐是排版效果,判题数据为单空格分隔(真机提交 AC 证实)。 O(1)
1084 九九乘法表(二) 反三角形:第 i 行输出 j=i…9;n 组数据,组与组之间输出一个空行。 O(n·81)
1085 字符统计(一) getline 读整行,用字符区间(a-z/A-Z/0-9/空格)分类统计,避开 isalpha 的 locale 影响。 O(行长)
1086 连续阶乘求和 double 边乘边加求 Σi!,用 %.0f 输出(与教材参考解一致)。 O(n)
1087 求式子的和 三项求和 Σk + Σk² + Σ1/k = 5050+42925+2.928968…,输出 6 位小数。 O(1)
1088 水仙花数 枚举 100…999,判断各位数字的立方和是否等于自身。 O(1)
1089 童年生活二三事 爬楼梯即斐波那契 f(1)=1,f(2)=2;多组输入读到 0 结束且不输出 0。 O(询问数)
1090 韩信点兵 韩信点兵:枚举满足「三三数之剩 a、五五数之剩 b、七七数之剩 c」的最小正整数。 O(105)
1091 小球蹦蹦跳 逐次反弹模拟:第 i 次落地路程加上 2 倍反弹高度,最后一次不再加反弹路程。 O(n)
1092 当月天数(数组实现) 月份天数数组 + 闰年修正 2 月,用数组实现而非 switch。 O(1)
1093 摘苹果 苹果高度 ≤ 手高 + 板凳高 即可摘到,逐个计数。 O(n)
1094 校门外的树 差分/标记:把每段砍树区间(含端点)打上标记,最后统计未被覆盖的树(共 L+1 棵)。 O(L+m)
1095 软件学院OJ 题目已被管理员停用(页面提示「题目当前不可用」),题面与测试数据均不可见。 —
1096 相同数个数 逐个比较,统计与给定值相同的元素个数。 O(n)
1097 冰雹猜想 冰雹猜想:奇数 3n+1、偶数 n/2,记录序列后倒序输出直到 1。 O(步数)
1098 卡片游戏 逐个数统计各数字的卡片需求,需求超过 30 张库存即停;注意 11 这种重复数字要一次扣两张 1。 O(答案位数)
1099 整数位序 整数位序:从最高位到最低位逐位输出各位数字。 O(位数)

1050 加班费

题面

1050 加班费

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

编写一个计算员工收入的程序,公司按照规定工时的工资10元/小时付给每个员工160个工时的薪水,按3倍的工资率付给160个工时以外的工资。

输入

输入员工的工时数,1个整数。

输出

计算员工的收入

来源/分类

样例输入

20

样例输出

200

思路:按 160 小时分段:未超出部分 10 元/时,超出部分 30 元/时(3 倍工资)。

复杂度:O(1)

参考代码:

// 1050 加班费
// 160 工时以内 10 元/小时;超出部分按 3 倍工资率(30 元/小时)
#include <bits/stdc++.h>
using namespace std;

int main() {
long long h;
while (cin >> h) {
long long ans;
if (h <= 160) ans = h * 10;
else ans = 160LL * 10 + (h – 160) * 30; // 超出部分按 3 倍
cout << ans << "\\n";
}
return 0;
}


1051 某年某月的天数

题面

1051 某年某月的天数

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

输入x和y,输出x年y月有多少天。

输入

一行两个正整数x和y,分别表示年份和月份。x在int范围以内,y为1~12。

输出

一行一个整数,表示该年该月有多少天。

来源/分类

样例输入

2021 3

样例输出

31

思路:月份天数打表,仅 2 月在闰年时改为 29;闰年判 (y%4==0&&y%100!=0)||y%400==0。

复杂度:O(1)

参考代码:

// 1051 某年某月的天数
#include <bits/stdc++.h>
using namespace std;

int main() {
long long x; // 年份(int 范围)
int y; // 月份 1~12
int d[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
while (cin >> x >> y) {
int ans = d[y];
if (y == 2) {
// 闰年:能被4整除且不能被100整除,或能被400整除
if ((x % 4 == 0 && x % 100 != 0) || x % 400 == 0) ans = 29;
}
cout << ans << "\\n";
}
return 0;
}


1052 蚂蚁的位置

题面

1052 蚂蚁的位置

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

有一只蚂蚁在一个圆上爬行,圆心坐标是(0,0),半径r=4.5,任意输入蚂蚁在圆上的坐标(x,y),判断这只蚂蚁是在圆内,圆周上,还是在圆外。

输入

两个浮点数x,y

输出

如果在圆内,输出in
如果在圆外,输出out
如果在圆上,输出on

来源/分类

样例输入

1.0 1.0

样例输出

in

思路:比较 x²+y² 与 r²=20.25,加 1e-6 容差后输出 in/on/out,避免临界点被浮点误差带偏。

复杂度:O(1)

参考代码:

// 1052 蚂蚁的位置:圆 x^2+y^2 = 4.5^2 = 20.25
#include <bits/stdc++.h>
using namespace std;

int main() {
double x, y;
const double R2 = 4.5 * 4.5; // 20.25
const double eps = 1e-6; // 浮点误差容限
while (cin >> x >> y) {
double d = x * x + y * y;
if (d < R2 – eps) cout << "in\\n";
else if (d > R2 + eps) cout << "out\\n";
else cout << "on\\n";
}
return 0;
}


1053 吃水果

题面

1053 吃水果

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

妈妈去超市买水果,她问小明想吃什么水果,现在超市只有五种水果,分别是Apple 苹果,Banana 香蕉,Cherry 樱桃,Durian 榴莲,Mango 芒果。如果小明说’A’,就是想吃Apple,如果小明说’B’,就是想吃Banana,如果小明说’C’,就是想吃Cherry ,如果小明说’D’,就是想吃Durian,如果小明随便说其它字母,妈妈就买Mango。
请采用switch语句实现。

输入

水果的英文单词首字母的大小形式

输出

水果的英文单词

来源/分类

样例输入

A

样例输出

Apple

思路:switch 映射 A/B/C/D → Apple/Banana/Cherry/Durian,大写小写同映射,其余 → Mango。

复杂度:O(1)

参考代码:

// 1053 吃水果:switch 实现,A/B/C/D -> 对应水果,其它 -> Mango
// 输入为首字母的大小写形式,两种都对应同一种水果
#include <bits/stdc++.h>
using namespace std;

int main() {
char ch;
if (cin >> ch) {
switch (ch) {
case 'A': case 'a': cout << "Apple\\n"; break;
case 'B': case 'b': cout << "Banana\\n"; break;
case 'C': case 'c': cout << "Cherry\\n"; break;
case 'D': case 'd': cout << "Durian\\n"; break;
default: cout << "Mango\\n"; break;
}
}
return 0;
}


1054 进制转换

题面

1054 进制转换

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

将一个二进制数,转换为对应的十进制数。

输入

输入一个只含有0和1的字符串,以回车结束,表示一个二进制数。该二进制数无符号位,长度不超过31。

输出

输出一个整数,为该二进制数对应的十进制数。

来源/分类

第4章循环结构

样例输入

100000000001

样例输出

2049

思路:按字符串读入二进制数(保留前导 0),逐位 v=v*2+(c-'0'),long long 承接 31 位。

复杂度:O(位数)

参考代码:

// 1054 进制转换:二进制字符串 -> 十进制(长度<=31,用 long long 防溢出)
#include <bits/stdc++.h>
using namespace std;

int main() {
string s;
while (cin >> s) {
long long v = 0;
for (size_t i = 0; i < s.size(); ++i)
v = v * 2 + (s[i] – '0');
cout << v << "\\n";
}
return 0;
}


1055 整数对数

题面

1055 整数对数

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

输入两个正整数m和n,输出m到n之间每个整数的自然对数。

输入

输入包括两个整数m和n(m < n),之间用一个空格隔开。

输出

每行输出一个整数及其对数,整数占4列,对数占8列,右对齐,对数保留4位小数。

来源/分类

样例输入

2 4

样例输出

2 0.6931
3 1.0986
4 1.3863

思路:printf("%4d%8.4f") —— 整数占 4 列、对数(自然对数 ln)占 8 列右对齐,占位列不能省。

复杂度:O(n-m+1)

参考代码:

// 1055 整数对数:整数占4列、对数占8列、右对齐、对数保留4位小数
#include <bits/stdc++.h>
using namespace std;

int main() {
int m, n;
while (cin >> m >> n) {
for (int i = m; i <= n; ++i)
printf("%4d%8.4f\\n", i, log((double)i)); // 自然对数 ln
}
return 0;
}


1056 整数数字

题面

1056 整数数字

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

输入一个正整数n(n ≤ 109),从高位开始逐位分割并输出各位数字。

输入

输入一个正整数n。

输出

依次输出各位上的数字,每一个数字后面有一个空格,输出占一行。

来源/分类

样例输入

12345

样例输出

1 2 3 4 5

思路:按字符串逐位输出每个数字,且每位数字后都跟一个空格。

复杂度:O(位数)

参考代码:

// 1056 整数数字:从高位到低位逐位输出,每个数字后面跟一个空格
#include <bits/stdc++.h>
using namespace std;

int main() {
long long n;
while (cin >> n) {
string s = to_string(n); // n 为正整数
for (size_t i = 0; i < s.size(); ++i)
printf("%c ", s[i]); // 每个数字后一个空格
printf("\\n");
}
return 0;
}


1057 优惠支付

题面

1057 优惠支付

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

双11来临,商场给出各种优惠活动,有满减券和打折券。小明也准备买几身漂亮衣服,好好把自己打扮一番。满减券和打折券可以同时使用,也可以使用一种,同时使用时先进行打折,打折后的金额再进行满减,请你计算一下小明需要支付多少钱?

输入

第一行输入两个整数表示满减优惠活动,例如:100 50表示每满100减50。第二行输入一个(0, 1)区间上的实数,表示打折优惠活动。以下多行输入所选商品的单价和数量,单价不一定是整数。

输出

输出购买商品最少需要支付的金额,保留两位小数。

提示

注意:本题样例存在满x减y(x<y)的情况,但支付金额不能为负。

来源/分类

样例输入

100 50
0.75
120 1
69 2

样例输出

143.50

思路:满减券/打折券可同用或只用一种,「最少支付」= 4 种方案(都不用 / 只打折 / 只满减 / 先折后减)取最小,每种金额钳 0 后输出 %.2f。真机验证:只算「先折后减」会挂数据(AC:95%),取 min 后 AC。

复杂度:O(商品行数)

参考代码:

// 1057 优惠支付:满减券与打折券可同时用/只用一种,求"最少"支付金额
// 4 种方案取最小:都不用 / 只打折 / 只满减 / 先打折后满减(题面规定同用时先折后减),
// 每种方案金额均不能为负(钳 0)。满减按"每满 x 减 y"计算次数。
#include <bits/stdc++.h>
using namespace std;

double clamp0(double v) { return v < 0 ? 0 : v; }

int main() {
long long x, y; // 每满 x 减 y
double disc; // 折扣率 (0,1)
if (!(cin >> x >> y)) return 0;
cin >> disc;

double total = 0.0; // 商品总价
double p, q; // 单价、数量
while (cin >> p >> q) total += p * q;

auto manjian = [&](double v) -> double {
long long cnt = 0;
if (x > 0) cnt = (long long)floor(v / (double)x + 1e-9);
return clamp0(v – (double)cnt * y);
};

double pay0 = clamp0(total); // 都不用
double pay1 = clamp0(total * disc); // 只打折
double pay2 = manjian(total); // 只满减
double pay3 = manjian(total * disc); // 先打折后满减

double ans = min(min(pay0, pay1), min(pay2, pay3));
printf("%.2f\\n", ans);
return 0;
}


1058 最不高兴

题面

1058 最不高兴

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

小明上初中了。妈妈认为小明应该更加用功学习,所以小明除了上学之外,还要参加妈妈为他报名的各科复习班。另外每周妈妈还会送他去学习朗诵、舞蹈和钢琴。但是小明如果一天上课超过八个小时就会不高兴,而且上得越久就会越不高兴。
假设小明不会因为其它事不高兴,并且他的不高兴不会持续到第二天。请你帮忙检查小明下周的日程安排,看看下周他是否会不高兴;如果会的话,哪天最不高兴?

输入

输入包括 7 行数据,分别表示周一到周日的日程安排。每行包括两个小于 10 的非负整数,用空格隔开,分别表示小明在学校上课的时间和妈妈安排他上课的时间。

输出

一个数字。如果不会不高兴则输出 0,如果会则输出最不高兴的是周几(用 1-7分别表示周一至周日)。如果有两天或两天以上不高兴的程度相当,则输出时间最靠前的一天。

来源/分类

样例输入

5 3
6 2
7 2
5 3
5 4
0 4
0 6

样例输出

3

思路:7 天求和,只有和数 >8 才算不高兴;严格比较保证并列时取最早的一天。

复杂度:O(1)

参考代码:

// 1058 最不高兴:7天,每天两段时间之和 >8 即不高兴,取最不高兴且最靠前的一天
#include <bits/stdc++.h>
using namespace std;

int main() {
int bestDay = 0, bestSum = –1;
for (int i = 1; i <= 7; ++i) {
int a, b;
cin >> a >> b;
int s = a + b;
if (s > bestSum) { bestSum = s; bestDay = i; } // 严格大于 => 并列取最靠前
}
if (bestSum <= 8) cout << 0 << "\\n";
else cout << bestDay << "\\n";
return 0;
}


1059 画矩形

题面

1059 画矩形

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

根据参数,画出矩形。

输入

输入一行,包括四个参数:前两个参数为整数,依次代表矩形的高和宽(高不少于3行不多于10行,宽不少于5列不多于10列);第三个参数是一个字符,表示用来画图的矩形符号;第四个参数为0或1,0代表空心,1代表实心。

输出

输出画出的图形。

来源/分类

样例输入

7 7 # 0

样例输出

#######
# #
# #
# #
# #
# #
#######

思路:实心每行 w 个字符;空心首末行 w 个字符、中间行两端各 1 个字符、中间留 w-2 个空格。

复杂度:O(h·w)

参考代码:

// 1059 画矩形:flag=1 实心;flag=0 空心
#include <bits/stdc++.h>
using namespace std;

int main() {
int h, w, flag;
char c;
while (cin >> h >> w >> c >> flag) {
for (int i = 0; i < h; ++i) {
if (flag == 1 || i == 0 || i == h – 1) {
for (int j = 0; j < w; ++j) putchar(c); // 实心行/上下边框
putchar('\\n');
} else {
putchar(c); // 空心行:边框 + 空格
for (int j = 0; j < w – 2; ++j) putchar(' ');
putchar(c);
putchar('\\n');
}
}
}
return 0;
}


1060 角谷猜想

题面

1060 角谷猜想

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

角谷猜想是指对于任意一个正整数,如果是奇数,则乘3加1,如果是偶数,则除以2,得到的结果再按照上述规则重复处理,最终总能够得到1。如,假定初始整数为5,计算过程分别为16、8、4、2、1。程序要求输入一个整数,将经过处理得到1的过程输出来。

输入

一个正整数N(N ≤ 106)。

输出

从输入整数到1的步骤,每一步为一行,每一步中描述计算过程。最后一行输出“End”。如果输入为1,直接输出“End”。

来源/分类

样例输入

5

样例输出

5*3+1=16
16/2=8
8/2=4
4/2=2
2/2=1
End

思路:角谷猜想:奇数 n=n*3+1、偶数 n=n/2,每步输出算式,最后输出 End。

复杂度:O(步数)

参考代码:

#include <bits/stdc++.h>
using namespace std;

// 1060 角谷猜想(3n+1 猜想)
// 奇数:n*3+1;偶数:n/2;每一步输出一行过程,最后输出 End;n=1 时直接输出 End。
int main() {
long long n;
if (scanf("%lld", &n) != 1) return 0;

// 过程中数值可能超过 int(例如 3n+1),用 long long 更稳妥
while (n != 1) {
if (n % 2 == 1) { // 奇数:乘 3 加 1
printf("%lld*3+1=%lld\\n", n, n * 3 + 1);
n = n * 3 + 1;
} else { // 偶数:除以 2
printf("%lld/2=%lld\\n", n, n / 2);
n /= 2;
}
}
printf("End\\n");
return 0;
}


1061 公式求值

题面

1061 公式求值

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

利用公式e = 1 + 1/1! + 1/2! + 1/3! + … + 1/n! 求e。

输入

输入只有一行,该行包含一个整数n(n ≥ 1),表示计算e时累加到1/n!。

输出

输出只有一行,该行包含计算出来的e的值,要求打印小数点后10位。

来源/分类

样例输入

10

样例输出

2.7182818011

思路:e=1+Σ1/i!,用 term/=i 递推避免直接算阶乘,输出 10 位小数。

复杂度:O(n)

参考代码:

#include <bits/stdc++.h>
using namespace std;

// 1061 公式求值:e = 1 + 1/1! + 1/2! + … + 1/n!,保留 10 位小数
int main() {
int n;
if (scanf("%d", &n) != 1) return 0;

double e = 1.0; // 第 0 项 1/0! = 1
double term = 1.0; // 当前项 1/i!
for (int i = 1; i <= n; ++i) {
term /= i; // 递推求 1/i!,避免直接算阶乘导致溢出
e += term;
}
printf("%.10f\\n", e);
return 0;
}


1062 整数累加

题面

1062 整数累加

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

求m+(m+1)+…+n。

输入

两个正整数m和n(m<n)。

输出

从m加到n的和。

来源/分类

样例输入

1 3

样例输出

6

思路:等差数列求和 (m+n)*(n-m+1)/2,用公式替代循环并防溢出。

复杂度:O(1)

参考代码:

#include <bits/stdc++.h>
using namespace std;

// 1062 整数累加:求 m+(m+1)+…+n(m<n,n 可能很大,用 long long 防溢出)
int main() {
long long m, n;
if (scanf("%lld %lld", &m, &n) != 2) return 0;

// 等差数列求和:(首项 + 末项) * 项数 / 2
long long sum = (m + n) * (n – m + 1) / 2;
printf("%lld\\n", sum);
return 0;
}


1063 多实例测试

题面

1063 多实例测试

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

输入多组数据,每组数据包含两个整数a和b,对每组数据输出a+b的结果。

输入

多组数据,每组一行,为两个以空格分隔的整数。

输出

对每组数据输出a+b的结果,每组结果占一行。

提示

保证结果都在整型范围内,并且 数据个数 ≤ 100

来源/分类

样例输入

1 2
3 4

样例输出

3
7

思路:多实例:while(scanf(…)==2) 读到 EOF,每组输出一行 a+b。

复杂度:O(组数)

参考代码:

#include <bits/stdc++.h>
using namespace std;

// 1063 多实例测试:读入到 EOF,每行一对 a b,输出 a+b
int main() {
long long a, b;
while (scanf("%lld %lld", &a, &b) == 2) { // 读到文件结束
printf("%lld\\n", a + b);
}
return 0;
}


1064 最小整数

题面

1064 最小整数

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

输入正整数n,求使1+2+…+i>=n成立的最小整数i。

输入

一个整数n。

输出

使1+2+…+i>=n成立的最小整数i。

来源/分类

样例输入

123

样例输出

16

思路:找最小 i 使 i(i+1)/2 ≥ n;用 sqrt 估算后双向微调,做到 O(1) 而非累加。

复杂度:O(1)

参考代码:

#include <bits/stdc++.h>
using namespace std;

// 1064 最小整数:求最小的 i 使 1+2+…+i >= n,即 i(i+1)/2 >= n
int main() {
long long n;
if (scanf("%lld", &n) != 1) return 0;

// 先用求根公式估算 i(解 i^2+i-2n=0),再做微调,避免朴素循环在大 n 时超时
long long i = (long long)((sqrtl(1.0L + 8.0L * (long double)n) – 1.0L) / 2.0L);
if (i < 1) i = 1;
// 用 long double 比较,避免大 n 时 i*(i+1) 溢出
while ((long double)i * (i + 1) / 2.0L < (long double)n) ++i; // 保证满足不等式
while (i > 1 && (long double)(i – 1) * i / 2.0L >= (long double)n) —i; // 保证 i 最小
printf("%lld\\n", i);
return 0;
}


1065 质数判断

题面

1065 质数判断

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

输入正整数n,判定它是否为素数(prime,又称质数)。

输入

一个正整数n。

输出

若n为质数则输出“Yes”,否则输出“No”。

提示

n 在整型范围内

来源/分类

样例输入

5

样例输出

Yes

思路:n≥2 才可能质数;试除到 sqrt(n),写成 i<=n/i 防止 i*i 溢出。

复杂度:O(√n)

参考代码:

#include <bits/stdc++.h>
using namespace std;

// 1065 质数判断:n 在整型范围内
int main() {
long long n;
if (scanf("%lld", &n) != 1) return 0;

// 1 不是质数;2 是最小的质数
bool prime = (n >= 2);
for (long long i = 2; i <= n / i; ++i) { // 试除到 sqrt(n),写成 n/i 可避免 i*i 溢出
if (n % i == 0) {
prime = false;
break;
}
}
printf("%s\\n", prime ? "Yes" : "No");
return 0;
}


1066 前n项和

题面

1066 前n项和

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

输入正整数n,求1-2/3+3/5-4/7+5/9-6/11+…的前n项和,结果保留3位小数。

输入

一个正整数n。

输出

求1-2/3+3/5-4/7+5/9-6/11+…的前n项和。

来源/分类

样例输入

100

样例输出

0.391

思路:第 i 项 = (-1)^(i-1)·i/(2i-1),累加后输出 3 位小数。

复杂度:O(n)

参考代码:

#include <bits/stdc++.h>
using namespace std;

// 1066 前n项和:1 – 2/3 + 3/5 – 4/7 + 5/9 – …
// 第 i 项为 (-1)^(i-1) * i/(2i-1),共 n 项,结果保留 3 位小数
int main() {
int n;
if (scanf("%d", &n) != 1) return 0;

double s = 0.0;
for (int i = 1; i <= n; ++i) {
double t = (double)i / (2.0 * i – 1.0);
if (i % 2 == 1) s += t; // 奇数项为正
else s -= t; // 偶数项为负
}
printf("%.3f\\n", s);
return 0;
}


1067 质数判断(break)

题面

1067 质数判断(break)

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

输入正整数n,判定它是否为素数(prime,又称质数),要求使用break语句。

输入

一个正整数n。

输出

若n为质数则输出“Yes”,否则输出“No”。

来源/分类

样例输入

7

样例输出

Yes

思路:与 1065 同解,显式用 break 在找到因子时提前跳出,满足题目对 break 的要求。

复杂度:O(√n)

参考代码:

#include <bits/stdc++.h>
using namespace std;

// 1067 质数判断(break):与 1065 相同,只是要求用 break 提前结束循环
int main() {
long long n;
if (scanf("%lld", &n) != 1) return 0;

bool prime = (n >= 2); // 1 不是质数,2 是质数
for (long long i = 2; i <= n / i; ++i) { // 试除到 sqrt(n),n/i 写法可避免 i*i 溢出
if (n % i == 0) {
prime = false;
break; // 找到因子立即跳出
}
}
printf("%s\\n", prime ? "Yes" : "No");
return 0;
}


1068 整数整除

题面

1068 整数整除

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

输出a到b之间的不能被3整除的整数。

输入

两个正整数a、b。

输出

a到b之间的不能被3整除的整数,以空格分隔。

来源/分类

样例输入

1 10

样例输出

1 2 4 5 7 8 10

思路:枚举 a…b 输出所有不能被 3 整除的数,用 first 标志控制空格以保证行末无空格。

复杂度:O(b-a)

参考代码:

#include <bits/stdc++.h>
using namespace std;

// 1068 整数整除:输出 [a,b] 之间所有不能被 3 整除的整数,空格分隔(行末无多余空格)
int main() {
long long a, b;
if (scanf("%lld %lld", &a, &b) != 2) return 0;

// 按题面“从 a 到 b”顺序遍历(题面保证 a、b 为正整数且 a 在前)
bool first = true;
for (long long i = a; i <= b; ++i) {
if (i % 3 != 0) {
if (!first) putchar(' '); // 数字之间才输出空格
printf("%lld", i);
first = false;
}
}
putchar('\\n');
return 0;
}


1069 m钱买m只鸡

题面

1069 m钱买m只鸡

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

公鸡五文钱一只,母鸡三文钱一只,小鸡一文钱三只,用m文钱买m只鸡,公鸡、母鸡、小鸡各买多少只?(仅考虑有解的情况)

输入

正整数m。

输出

公鸡、母鸡和小鸡的只数(若有多个解则仅输出公鸡数量最少的那个解)。

提示

来源/分类

样例输入

100

样例输出

0 25 75

思路:消元得 7x+4y=m,x 从 0 枚举,首个可行解即公鸡最少的解;输出顺序为 公鸡 母鸡 小鸡。

复杂度:O(m)

参考代码:

#include <bits/stdc++.h>
using namespace std;

// 1069 m钱买m只鸡
// 设公鸡 x、母鸡 y、小鸡 z:x + y + z = m,5x + 3y + z/3 = m(z 为 3 的倍数)
// 消元得:7x + 4y = m,即 y = (m – 7x)/4,z = m – x – y = 3(m + x)/4
// x 从 0 开始枚举,第一个可行解即为公鸡数量最少的解。
int main() {
long long m;
if (scanf("%lld", &m) != 1) return 0;

for (long long x = 0; x <= m; ++x) {
long long r = m – 7 * x;
if (r < 0) break; // y 会为负,之后更不可能
if (r % 4 != 0) continue; // y 必须是整数
long long y = r / 4;
long long z = m – x – y;
if (z < 0 || z % 3 != 0) continue;
if (5 * x + 3 * y + z / 3 == m) { // 再按原方程校验一次
printf("%lld %lld %lld\\n", x, y, z);
return 0;
}
}
return 0; // 题面保证有解
}


1070 质数数目

题面

1070 质数数目

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

统计a到b之间存在多少个质数。

输入

两个正整数a、b。

输出

a到b之间的全部质数的数目。

提示

来源/分类

样例输入

100 200

样例输出

21

思路:区间筛:先用试除筛出 √b 内的质数,再按段筛 [a,b] 并计数;注意 1 不是质数。

复杂度:O(√b+(b-a))

参考代码:

#include <bits/stdc++.h>
using namespace std;

// 1070 质数数目:统计 [a,b] 内的质数个数
// 采用分段筛(埃氏筛的按段实现):先筛出 sqrt(b) 以内的质数做"筛子",
// 再把 [a,b] 切成每段 1e6 个数逐个筛掉合数,区间很大也不会爆内存。
int main() {
long long a, b;
if (scanf("%lld %lld", &a, &b) != 2) return 0;
if (a > b) swap(a, b); // 保险:保证 a<=b
if (b < 2) { printf("0\\n"); return 0; } // 区间里没有质数
if (a < 2) a = 2; // 1 不是质数

// 1) 筛出 sqrt(b) 以内的所有质数
long long lim = (long long)sqrtl((long double)b) + 1;
vector<char> comp((size_t)lim + 1, 0);
vector<long long> base;
for (long long i = 2; i <= lim; i++) {
if (!comp[i]) {
base.push_back(i);
for (long long j = i * i; j <= lim; j += i) comp[j] = 1;
}
}

// 2) 逐段筛 [a,b]
const long long CH = 1 << 20; // 每段长度
vector<char> seg((size_t)CH, 0);
long long cnt = 0;
for (long long L = a; L <= b; L += CH) {
long long R = min(b, L + CH – 1);
fill(seg.begin(), seg.begin() + (size_t)(R – L + 1), 0);
for (size_t k = 0; k < base.size(); k++) {
long long p = base[k];
if (p * p > R) break; // 大于 sqrt(R) 的质数不用再筛
long long st = max(p * p, (L + p – 1) / p * p); // 段内第一个 p 的倍数
for (long long j = st; j <= R; j += p) seg[(size_t)(j – L)] = 1;
}
for (long long x = L; x <= R; x++)
if (!seg[(size_t)(x – L)]) cnt++;
}
printf("%lld\\n", cnt);
return 0;
}


1071 m钱买m只鸡(无解输出“No answer”)

题面

1071 m钱买m只鸡(无解输出“No answer”)

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

公鸡五文钱一只,母鸡三文钱一只,小鸡一文钱三只,用m文钱买m只鸡,公鸡、母鸡、小鸡各买多少只?(既考虑有解的情况,又考虑无解的情况)

输入

一个正整数m。

输出

若有解只输出一个解,即公鸡数量最少的那个解;若无解输出“No answer”。

提示

来源/分类

样例输入

100

样例输出

0 25 75

思路:同 1069 的消元枚举,无解时输出半角 No answer。

复杂度:O(m)

参考代码:

#include <bits/stdc++.h>
using namespace std;

// 1071 m钱买m只鸡:公鸡5文、母鸡3文、小鸡1文3只
// 设公鸡 r、母鸡 h、小鸡 c:r+h+c=m, 5r+3h+c/3=m
// 消元得 c = 3(m+r)/4,h = m-r-c;r 从小到大枚举即"公鸡最少"
int main() {
long long m;
if (scanf("%lld", &m) != 1) return 0;

for (long long r = 0; r <= m; r++) {
long long s = m + r;
if (s % 4 != 0) continue; // 小鸡数必须为整数(3*s/4)
long long c = 3 * s / 4;
long long h = m – r – c;
if (h >= 0 && c >= 0) { // 找到公鸡最少的解
printf("%lld %lld %lld\\n", r, h, c);
return 0;
}
}
printf("No answer\\n");
return 0;
}


1072 整数的位数(while实现)

题面

1072 整数的位数(while实现)

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

输入一个正整数,输出其位数(用while语句实现)。

输入

一个正整数。

输出

正整数的位数。

来源/分类

样例输入

123

样例输出

3

思路:while(n>0){cnt++;n/=10;} 逐位去掉末位计数,用 long long。

复杂度:O(位数)

参考代码:

#include <bits/stdc++.h>
using namespace std;

// 1072 整数的位数(while实现)
int main() {
long long n;
if (scanf("%lld", &n) != 1) return 0;

int cnt = 0;
while (n > 0) { // 每次去掉最低位,去掉几位就是几位数
cnt++;
n /= 10;
}
printf("%d\\n", cnt);
return 0;
}


1073 数字反转

题面

1073 数字反转

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

给定一个整数,请将该数各个数位上的数字反转得到一个新数。新数也应满足整数的常见形式,即除非给定的原数为零,否则反转后得到的新数的最高位数字不应为零。

输入

一个十进制整数。

输出

对应的反转数。

提示

保证数据≤100000

来源/分类

样例输入

-690

样例输出

-96

思路:取绝对值后算术反转再补符号,末尾的 0 自然消失(1200→21)。

复杂度:O(位数)

参考代码:

#include <bits/stdc++.h>
using namespace std;

// 1073 数字反转:-690 -> -96,1200 -> 21(新数不能有前导零)
int main() {
long long n;
if (scanf("%lld", &n) != 1) return 0;

if (n == 0) { printf("0\\n"); return 0; } // 原数为 0 时反转仍是 0

int sign = 1;
if (n < 0) { sign = –1; n = –n; } // 先按正数处理,最后补符号

long long rev = 0;
while (n > 0) {
rev = rev * 10 + n % 10; // 末尾的 0 自然被丢掉
n /= 10;
}
printf("%lld\\n", sign * rev);
return 0;
}


1074 礼物数量

题面

1074 礼物数量

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

小明买了许多礼物准备用于班级活动,回家后感觉太累了,便让机器人小灵帮忙数一下礼物一共有多少份。但是小灵不喜欢数字4,因此每次数到包含数字4时便跳过该数。例如小灵数到639时,下一份礼物小灵就会数650。

输入

一个不含4的正整数n,表示小灵给出的礼物的份数。

输出

一个整数代表礼物的实际份数。

来源/分类

样例输入

55

样例输出

40

思路:第 n 个不含数字 4 的正整数:把 n 的各位当作 9 进制加权,数字 >4 时减 1。

复杂度:O(位数)

参考代码:

#include <bits/stdc++.h>
using namespace std;

// 1074 礼物数量:小灵从 1 开始数且跳过所有含数字 4 的数,
// 它报出的 n 在"不含4数列"中的序号就是实际份数。
// 把 n 的每一位数字按 9 进制位值累加(>=5 的数字减 1)即得序号。
int main() {
long long n;
if (scanf("%lld", &n) != 1) return 0;

long long ans = 0, base = 1; // base = 9 的幂
while (n > 0) {
int d = (int)(n % 10);
if (d > 4) d—; // 1..3 不变,5..9 减 1(4 不会出现)
ans += (long long)d * base;
base *= 9;
n /= 10;
}
printf("%lld\\n", ans);
return 0;
}


1075 分解质因子

题面

1075 分解质因子

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

将一个整数表示为其质因子相乘形式。

输入

一个正整数n。

输出

n的质因数的乘积形式。

来源/分类

样例输入

36

样例输出

2*2*3*3

思路:从小到大试除分解质因子,用 * 连接输出(按题面样例不加 n= 前缀)。

复杂度:O(√n)

参考代码:

#include <bits/stdc++.h>
using namespace std;

// 1075 分解质因子:输出形如 2*2*3*3(题面样例没有 "n=" 前缀)
int main() {
long long n;
if (scanf("%lld", &n) != 1) return 0;

if (n == 1) { printf("1\\n"); return 0; } // 1 没有质因子,乘积形式为 1

long long x = n;
bool first = true; // 控制 '*' 不打印在最前面
for (long long p = 2; p * p <= x; p++) { // x 不断变小,循环上界随之收缩
while (x % p == 0) {
if (!first) printf("*");
printf("%lld", p);
first = false;
x /= p;
}
}
if (x > 1) { // 剩下的一定是质数
if (!first) printf("*");
printf("%lld", x);
}
printf("\\n");
return 0;
}


1076 数列累加

题面

1076 数列累加

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

输入n和a,求a+aa+aaa+…aa…a(n个a),如当n=3,a=2时,2+22+222=246。

输入

包含两个整数,n和a,含义如上述,n和a都是小于10的非负整数。

输出

输出前n项和,单独占一行

来源/分类

样例输入

3 2

样例输出

246

思路:term=term*10+a 生成 a, aa, aaa… 并累加,用 long long 防溢出。

复杂度:O(n·位数)

参考代码:

#include <bits/stdc++.h>
using namespace std;

// 1076 数列累加:a+aa+aaa+…(n 项,n 与 a 都小于 10)
// 用 long long 防溢出(9+99+…+999999999 超过 int)
int main() {
int n, a;
if (scanf("%d %d", &n, &a) != 2) return 0;

long long term = 0, sum = 0;
for (int i = 0; i < n; i++) {
term = term * 10 + a; // 2 -> 22 -> 222
sum += term;
}
printf("%lld\\n", sum);
return 0;
}


1077 零花钱奖励

题面

1077 零花钱奖励

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

妈妈给了小明m张百元钞票,为了鼓励小明节约,说如果小明连续k天每天仅花10元,就可以得到10元额外奖励,如果听妈妈的话小明最多可以花多少天?

输入

输入2个整数m、k,(2 <= k<=m<= 1000)。

输出

输出一个整数,表示m元可以消费的天数。

来源/分类

样例输入

4 3

样例输出

59

思路:m 是百元钞票张数(总额 100m);逐天模拟,连续攒够 k 天即 +10 元并重置计数。

复杂度:O(天数)

参考代码:

#include <bits/stdc++.h>
using namespace std;

// 1077 零花钱奖励:m 张百元钞票共 100*m 元,每天花 10 元;
// 每连续 k 天只花 10 元就再得 10 元奖励(奖励可以继续用来花)。
// 逐天模拟:花得起就花,攒够 k 天立刻发奖。
int main() {
long long m, k;
if (scanf("%lld %lld", &m, &k) != 2) return 0;

long long money = m * 100; // 总钱数(元)
long long days = 0, streak = 0; // 已花的连续天数
while (money >= 10) {
money -= 10;
days++;
streak++;
if (streak == k) { // 连续 k 天达成,给 10 元奖励
money += 10;
streak = 0;
}
}
printf("%lld\\n", days);
return 0;
}


1078 阶乘最高位

题面

1078 阶乘最高位

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

Normal07.8 磅02falsefalsefalseMicrosoftInternetExplorer4
输入一个正整数n。输出n!的最高位上的数字。

输入

输入一个正整数n(n<=1000)。

输出

Normal07.8 磅02falsefalsefalseMicrosoftInternetExplorer4
输出n!的最高位上的数字。

来源/分类

样例输入

1000

样例输出

4

思路:阶乘首位:用 long double 累加对数,首位 = ⌊10^小数部分⌋,避免直接算阶乘。

复杂度:O(n)

参考代码:

#include <bits/stdc++.h>
using namespace std;

// 1078 阶乘最高位:n<=1000,n! 用 long double 存放不下,
// 改用对数法:log10(n!) = 1*log10(1)+…+log10(n),
// 小数部分 f 满足 n! = 10^(整数部分+f),最高位 = floor(10^f)。
int main() {
int n;
if (scanf("%d", &n) != 1) return 0;

if (n <= 1) { printf("1\\n"); return 0; } // 0! = 1! = 1

long double s = 0.0L;
for (int i = 2; i <= n; i++) s += log10l((long double)i);

long double f = s – floorl(s); // 小数部分
int d = (int)floorl(powl(10.0L, f)); // 首位数字
if (d < 1) d = 1;
if (d > 9) d = 9;
printf("%d\\n", d);
return 0;
}


1079 小车的位置

题面

1079 小车的位置

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

有一辆智能小车,最初(时间为0)的位置为(0,0),我们想知道它最后的位置。小车以每小时10公里的速度向北移动(北为y轴正向,东为x轴正向)。小车会收到一系列依照时间戳记排序的命令,1表示“向左转”,2表示“向右转”,3表示“停止”。每个命令的前面有一个时间戳记,所以知道该命令是何时发出的。最后一个命令一定是“停止”。另外假设,这辆小车非常灵活,它可以在瞬间转弯。
例,小车在时间为5时收到一个“向左转”的命令1,在时间10收到一个“向右转”的命令2,在时间15收到一个“停止”的命令3。那么在最后时间15时,小车的位置将在(-50,100)。程序只要求输出小车最后的位置,第一个整数是x坐标,第二个整数是y坐标。

输入

输入包含多个命令,每个命令由整数time和command组成,表示在时刻time发出命令command。command的取值范围1-3,含义如上所述。

输出

Normal07.8 磅02falsefalsefalseMicrosoftInternetExplorer4
输出占一行,包含两个整数,表示小车的最终位置。两个整数之间由空格隔开。

来源/分类

样例输入

5 1
10 2
15 3

样例输出

-50 100

思路:方向数组 {北,西,南,东},先按 (t-prev)*10 行驶再执行转向/停止命令。

复杂度:O(命令数)

参考代码:

#include <bits/stdc++.h>
using namespace std;

// 1079 小车的位置:起点 (0,0),速度 10/小时,初始朝北(y 轴正向)。
// 每读到一条命令,先按"上一时刻->本时刻"的时长沿当前方向前进,
// 再执行转弯(1 左转、2 右转、3 停止);命中的最后一个命令一定是 3。
int main() {
// 方向顺序:0 北、1 西、2 南、3 东(左转 +1,右转 +3,正好是同一套下标)
int dx[4] = {0, –1, 0, 1};
int dy[4] = {1, 0, –1, 0};

int t, c, prev = 0, dir = 0;
long long x = 0, y = 0;

while (scanf("%d %d", &t, &c) == 2) {
long long dt = (long long)t – prev; // 本段行驶时长
x += (long long)dx[dir] * 10 * dt;
y += (long long)dy[dir] * 10 * dt;
prev = t;

if (c == 1) dir = (dir + 1) % 4; // 左转
else if (c == 2) dir = (dir + 3) % 4; // 右转
else break; // 3:停止,位置就是终点
}
printf("%lld %lld\\n", x, y);
return 0;
}


1080 乘积反转

题面

1080 乘积反转

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

做作业的时候,邻座的小朋友问你:“五乘以七等于多少?”你应该不失礼貌地微笑着告诉他:“五十三”。本题要求对任何一对给定的正整数,逆向输出它们的乘积。

输入

输入一行,给出两个不超过 1000 的正整数 a 和 b,以空格分隔。

输出

在一行中逆向输出 a 和 b 的乘积。

提示

注意前导0不要输出。

来源/分类

样例输入

50 7

样例输出

53

思路:a*b 后逐位反转拼接 r=r*10+n%10,前导零自然丢弃。

复杂度:O(位数)

参考代码:

// 1080 乘积反转
// 思路:先求 a*b,再把乘积的数字逆序“拼”回来(自然去掉前导零)。
#include <bits/stdc++.h>
using namespace std;

int main() {
long long a, b;
if (scanf("%lld %lld", &a, &b) != 2) return 0;
long long n = a * b; // a,b<=1000,乘积最大 10^6,long long 足够
long long r = 0;
while (n > 0) {
r = r * 10 + n % 10; // 逆序构造,前导零自动消失
n /= 10;
}
printf("%lld\\n", r);
return 0;
}


1081 两个数的最大公约数

题面

1081 两个数的最大公约数

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

输入2个正整数a,b,求a与b的最大公约数。

输入

2个正整数a,b,中间用空格隔开。(1<=a,b <= 104)

输出

输出a与b的最大公约数。

来源/分类

样例输入

6 15

样例输出

3

思路:辗转相除法(欧几里得算法)求最大公约数。

复杂度:O(log min(a,b))

参考代码:

// 1081 两个数的最大公约数
// 思路:辗转相除法(欧几里得算法)。
#include <bits/stdc++.h>
using namespace std;

int main() {
long long a, b;
if (scanf("%lld %lld", &a, &b) != 2) return 0;
while (b != 0) {
long long t = a % b;
a = b;
b = t;
}
printf("%lld\\n", a); // 循环结束时 a 即 gcd
return 0;
}


1082 两个数的最小公倍数

题面

1082 两个数的最小公倍数

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

正整数a和正整数b的最小公倍数是指能被a和b整除的最小的正整数值,设计一个算法,求输入a和b的最小公倍数。

输入

输入两个正整数a和b。

输出

输出a和b的最小公倍数。

来源/分类

样例输入

5 3

样例输出

15

思路:a/gcd*b —— 先除后乘,避免 a*b 溢出。

复杂度:O(log min(a,b))

参考代码:

// 1082 两个数的最小公倍数
// 思路:lcm(a,b) = a / gcd(a,b) * b,先除后乘避免溢出。
#include <bits/stdc++.h>
using namespace std;

int main() {
long long a, b;
if (scanf("%lld %lld", &a, &b) != 2) return 0;
long long x = a, y = b;
while (y != 0) { // 辗转相除求 gcd
long long t = x % y;
x = y;
y = t;
}
printf("%lld\\n", a / x * b);
return 0;
}


1083 九九乘法表(一)

题面

1083 九九乘法表(一)

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

我们小时候学过的九九乘法表也许终生难忘,现在让我们重温这个美好的记忆,请编程输出九九乘法表。

输入

无

输出

11=1
21=2 22=4
31=3 32=6 33=9
41=4 42=8 43=12 44=16
51=5 52=10 53=15 54=20 55=25
61=6 62=12 63=18 64=24 65=30 66=36
71=7 72=14 73=21 74=28 75=35 76=42 77=49
81=8 82=16 83=24 84=32 85=40 86=48 87=56 88=64
91=9 92=18 93=27 94=36 95=45 96=54 97=63 98=72 9*9=81

来源/分类

样例输入

无

样例输出

1*1=1
2*1=2 2*2=4
3*1=3 3*2=6 3*3=9
4*1=4 4*2=8 4*3=12 4*4=16
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81

思路:第 i 行输出 j=1…i,格式 i*j=i*j,项间单空格、行末无空格。注意:题面样例里的宽对齐是排版效果,判题数据为单空格分隔(真机提交 AC 证实)。

复杂度:O(1)

参考代码:

// 1083 九九乘法表(一)
// 思路:第 i 行输出 j=1..i 的 "i*j=i*j",乘数顺序为 i*j。
// 格式:题面「输出」部分为单空格分隔(判题数据以此为准;样例里的对齐空格是排版效果),
// 项间一个空格,行末无空格。
#include <bits/stdc++.h>
using namespace std;

int main() {
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; j++) {
if (j > 1) printf(" "); // 项间单空格
printf("%d*%d=%d", i, j, i * j); // 乘数顺序:i*j
}
printf("\\n");
}
return 0;
}


1084 九九乘法表(二)

题面

1084 九九乘法表(二)

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

请按要求输出九九乘法表。要求所输出它的格式与平常的不同,是那种反过来的三角形,可不要看错了!

输入

第一行有一个整数,表示有n组数据。(n<10)
接下来有n行,每行只有一个整数m(1<=m<= 9)。

输出

对应每个整数m,根据要求输出乘法表的前m行,具体格式参见输入样例.
每两组测试数据结果之间有一个空行隔开,具体如输出样例。

提示

来源/分类

样例输入

3
2
1
5

样例输出

1*1=1 1*2=2 1*3=3 1*4=4 1*5=5 1*6=6 1*7=7 1*8=8 1*9=9
2*2=4 2*3=6 2*4=8 2*5=10 2*6=12 2*7=14 2*8=16 2*9=18

1*1=1 1*2=2 1*3=3 1*4=4 1*5=5 1*6=6 1*7=7 1*8=8 1*9=9

1*1=1 1*2=2 1*3=3 1*4=4 1*5=5 1*6=6 1*7=7 1*8=8 1*9=9
2*2=4 2*3=6 2*4=8 2*5=10 2*6=12 2*7=14 2*8=16 2*9=18
3*3=9 3*4=12 3*5=15 3*6=18 3*7=21 3*8=24 3*9=27
4*4=16 4*5=20 4*6=24 4*7=28 4*8=32 4*9=36
5*5=25 5*6=30 5*7=35 5*8=40 5*9=45

思路:反三角形:第 i 行输出 j=i…9;n 组数据,组与组之间输出一个空行。

复杂度:O(n·81)

参考代码:

// 1084 九九乘法表(二)
// 思路:n 组数据,每组给定 m,输出“反过来的三角形”前 m 行:
// 第 i 行输出 j=i..9 的 "i*j=i*j",项间一个空格;
// 相邻两组结果之间输出一个空行。
#include <bits/stdc++.h>
using namespace std;

int main() {
int n;
if (scanf("%d", &n) != 1) return 0;
for (int t = 1; t <= n; t++) {
int m;
if (scanf("%d", &m) != 1) break;
if (t > 1) printf("\\n"); // 两组之间的空行
for (int i = 1; i <= m; i++) { // 只输出前 m 行
for (int j = i; j <= 9; j++) { // 每行从 i*i 一直到 i*9
if (j > i) printf(" ");
printf("%d*%d=%d", i, j, i * j);
}
printf("\\n");
}
}
return 0;
}


1085 字符统计(一)

题面

1085 字符统计(一)

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

输入一行字符,分别统计其中英文字母、空格、数字和其他字符的个数,分行输出该结果。

输入

一行字符,可以包含字母、数字、空格、标点等符号。

输出

分行输出大小写英文字母、空格、数字和其他字符的个数。
如:
characters=字母个数
spaces=空格个数
numbers=数字个数
others=其他字符个数

提示

来源/分类

样例输入

My input123 @%chars.

样例输出

characters=12
spaces=2
numbers=3
others=3

思路:getline 读整行,用字符区间(a-z/A-Z/0-9/空格)分类统计,避开 isalpha 的 locale 影响。

复杂度:O(行长)

参考代码:

// 1085 字符统计(一)
// 思路:读入一整行,逐字符分类计数:英文字母 / 空格 / 数字 / 其他。
// 判定用字符范围比较,避免受 locale 影响。
#include <bits/stdc++.h>
using namespace std;

int main() {
string s;
if (!getline(cin, s)) s = ""; // 极端情况:空行则四个计数均为 0
int letters = 0, spaces = 0, digits = 0, others = 0;
for (size_t i = 0; i < s.size(); i++) {
char c = s[i];
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) letters++;
else if (c == ' ') spaces++;
else if (c >= '0' && c <= '9') digits++;
else others++;
}
printf("characters=%d\\n", letters);
printf("spaces=%d\\n", spaces);
printf("numbers=%d\\n", digits);
printf("others=%d\\n", others);
return 0;
}


1086 连续阶乘求和

题面

1086 连续阶乘求和

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

输入一个正整数N,求1!+2!+3!+…+N!,即求

输入

输入一个正整数N。

输出

1~N连续阶乘的和,1!+2!+3!+…+N!的和,末尾换行。

提示

由于大于10的整数的阶乘非常大,已超出整数的表示范围,故求阶乘时,需要将变量定义为double类型。

来源/分类

样例输入

10

样例输出

4037913

思路:double 边乘边加求 Σi!,用 %.0f 输出(与教材参考解一致)。

复杂度:O(n)

参考代码:

// 1086 连续阶乘求和
// 思路:按题面提示,阶乘与和都用 double 保存(N 较大时阶乘超出整数范围),
// 边乘边加:f = i!,s 累加;最后按整数形式输出(保留 0 位小数)。
#include <bits/stdc++.h>
using namespace std;

int main() {
int n;
if (scanf("%d", &n) != 1) return 0;
double f = 1.0, s = 0.0;
for (int i = 1; i <= n; i++) {
f *= i; // f = i!
s += f; // 累加 1!+2!+…+i!
}
printf("%.0f\\n", s);
return 0;
}


1087 求式子的和

题面

1087 求式子的和

时间限制 1.000 sec / 内存限制 64 MiB

题目描述

求如下式子的和
请将结果定义为double类型。
注意求平方,不要用C数学库中提供的函数pow。

输入

无

输出

小数点后保留6位小数,末尾换行。

来源/分类

样例输入

无

样例输出

47977.928968

思路:三项求和 Σk + Σk² + Σ1/k = 5050+42925+2.928968…,输出 6 位小数。

复杂度:O(1)

参考代码:

// 1087 求式子的和
// 式子:sum(k, k=1..100) + sum(k^2, k=1..50) + sum(1/k, k=1..10)
// = 5050 + 42925 + 2.928968… = 47977.928968…
// 思路:用 double 累加,平方用 k*k 直接相乘,输出保留 6 位小数。
#include <bits/stdc++.h>
using namespace std;

int main() {
double s = 0.0;
for (int k = 1; k <= 100; k++) s += k; // 第一项:1+2+…+100
for (int k = 1; k <= 50; k++) s += (double)k * k; // 第二项:1^2+2^2+…+50^2
for (int k = 1; k <= 10; k++) s += 1.0 / k; // 第三项:1/1+1/2+…+1/10
printf("%.6f\\n", s);
return 0;
}


1088 水仙花数

题面

1088 水仙花数

时间限制 1.000 sec / 内存限制 64 MiB

题目描述

春天是鲜花的季节,水仙花就是其中最迷人的代表,数学上有个水仙花数,它是这样定义的:“水仙花数”是指一个三位数,它的各位数字的立方和等于其本身,比如:153=13+53+33。请输出所有的“水仙花数”。

输入

无

输出

每行输出一个水仙花数。

来源/分类

样例输入

无

样例输出

153
370
371
407

思路:枚举 100…999,判断各位数字的立方和是否等于自身。

复杂度:O(1)

参考代码:

// 1088 水仙花数
// 思路:枚举全部三位数 100..999,判断各位数字立方和是否等于自身,每行输出一个。
#include <bits/stdc++.h>
using namespace std;

int main() {
for (int i = 100; i <= 999; i++) {
int a = i / 100; // 百位
int b = i / 10 % 10; // 十位
int c = i % 10; // 个位
if (a * a * a + b * b * b + c * c * c == i)
printf("%d\\n", i);
}
return 0;
}


1089 童年生活二三事

题面

1089 童年生活二三事

时间限制 1.000 sec / 内存限制 64 MiB

题目描述

Redraiment小时候走路喜欢蹦蹦跳跳,他最喜欢在楼梯上跳来跳去。 但年幼的他一次只能走上一阶或者一下子蹦上两阶。 现在一共有N阶台阶,请你计算一下Redraiment从第0阶到第N阶共有几种走法。

输入

输入包括多组数据。 每组数据包括一行:N(1≤N≤40)。 输入以0结束。

输出

对应每个输入包括一个输出。 为redraiment到达第n阶不同走法的数量。

来源/分类

样例输入

1
2
0

样例输出

1
2

思路:爬楼梯即斐波那契 f(1)=1,f(2)=2;多组输入读到 0 结束且不输出 0。

复杂度:O(询问数)

参考代码:

// 1089 童年生活二三事
// 思路:每次只能走 1 阶或 2 阶,走法数即斐波那契:
// f(1)=1, f(2)=2, f(n)=f(n-1)+f(n-2);N<=40 用 long long 打表。
// 多组输入,读到 0 结束。
#include <bits/stdc++.h>
using namespace std;

int main() {
const int LIM = 92; // 题目保证 N<=40,多打一段表以防越界(long long 足够容纳该数列前 92 项)
static long long f[LIM + 1];
f[0] = 1;
f[1] = 1; // 走到第 1 阶:1 种
for (int i = 2; i <= LIM; i++) f[i] = f[i – 1] + f[i – 2]; // 第 2 阶为 2 种
int n;
while (scanf("%d", &n) == 1 && n != 0) {
printf("%lld\\n", f[n]);
}
return 0;
}


1090 韩信点兵

题面

1090 韩信点兵

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

淮安民间传说着一则故事——“韩信点兵”,相关成语“韩信点兵,多多益善”。韩信从不直接清点自己军队的人数,只要让士兵先后以三人一排、五人一排、七人一排地变换队形,而他每次只掠一眼队伍的排尾就知道总人数了。
输入3个非负整数a,b,c ,表示每种队形排尾的人数(a<3,b<5,c<7),输出总人数的最小值(或报告无解)。已知总人数不小于10,不超过100 。

输入

输入3个非负整数 ,表示每种队形排尾的人数(a<3,b<5,c<7)。例如,输入:2 4 5

输出

输出总人数的最小值(或报告无解,即输出No answer)。实例,输出:89

来源/分类

样例输入

2 1 6

样例输出

41

思路:韩信点兵:枚举满足「三三数之剩 a、五五数之剩 b、七七数之剩 c」的最小正整数。

复杂度:O(105)

参考代码:

// 1090 韩信点兵
// 总人数 n 满足 10 <= n <= 100,且 n%3==a, n%5==b, n%7==c
// 直接从小到大枚举第一个满足条件的即为最小值;无解输出 No answer
#include <bits/stdc++.h>
using namespace std;

int main() {
int a, b, c;
while (scanf("%d %d %d", &a, &b, &c) == 3) {
int ans = –1;
for (int n = 10; n <= 100; n++) {
if (n % 3 == a && n % 5 == b && n % 7 == c) {
ans = n;
break; // 第一个满足的就是最小值
}
}
if (ans < 0)
printf("No answer\\n");
else
printf("%d\\n", ans);
}
return 0;
}


1091 小球蹦蹦跳

题面

1091 小球蹦蹦跳

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

调皮的小明将皮球从100m的高度自由落下,每次落地后反弹回原高度的一半,再落下,再反弹。
求它在第N次落地时,共经过了多少米,第N次反弹多高。

输入

一个正整数N,表示球落地的次数。

输出

length=球第N次落地时所经过了距离
high=球第N次落地反弹的高度
小数点后保留4位小数。
注意:末尾输出换行。

来源/分类

样例输入

10

样例输出

length=299.6094
high=0.0977

思路:逐次反弹模拟:第 i 次落地路程加上 2 倍反弹高度,最后一次不再加反弹路程。

复杂度:O(n)

参考代码:

// 1091 小球蹦蹦跳
// 从 100m 落下,每次落地后反弹回原高度的一半
// 第 i 次落地时经过的路程:i=1 时就是 100;之后每次多走 2*上一次反弹高度
// 第 N 次落地后的反弹高度 = 100 / 2^N
#include <bits/stdc++.h>
using namespace std;

int main() {
int n;
if (scanf("%d", &n) != 1) return 0;
double h = 100.0; // 当前高度:第一次落地前为 100,之后为上一次反弹高度
double len = 0.0; // 累计经过的路程
for (int i = 1; i <= n; i++) {
len += h; // 落下这一段
h /= 2.0; // 反弹高度(第 i 次落地后的反弹高度)
if (i < n) len += h; // 不是最后一次落地,还要把这次弹起再落下的上升段计入
}
printf("length=%.4f\\n", len);
printf("high=%.4f\\n", h);
return 0;
}


1092 当月天数(数组实现)

题面

1092 当月天数(数组实现)

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

输入年份和月份,输出这一年的这一月有多少天。

输入

输入两个正整数,分别表示年份y 和月份m,以空格分隔。

输出

输出一个正整数,表示这个月有多少天。

来源/分类

第5章数组

样例输入

2000 2

样例输出

29

思路:月份天数数组 + 闰年修正 2 月,用数组实现而非 switch。

复杂度:O(1)

参考代码:

// 1092 当月天数(数组实现)
// 用数组存每月天数,闰年时 2 月改为 29
#include <bits/stdc++.h>
using namespace std;

int main() {
int days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int y, m;
if (scanf("%d %d", &y, &m) != 2) return 0;
bool leap = (y % 400 == 0) || (y % 4 == 0 && y % 100 != 0);
if (leap) days[2] = 29;
printf("%d\\n", days[m]);
return 0;
}


1093 摘苹果

题面

1093 摘苹果

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

小明家的院子里有一棵苹果树,每到秋天树上就会结出10个苹果。苹果成熟的时候,小明就会跑去摘苹果。小明有个30厘米高的板凳,当他不能直接用手摘到苹果的时候,就会踩到板凳上再试试。现在已知10个苹果到地面的高度,以及小明把手伸直的时候能够达到的最大高度,请帮小明算一下他能够摘到的苹果的数目。假设他碰到苹果,苹果就会掉下来。

输入

包括两行数据。第一行包含10个100到200之间(包括100和200)的整数(以厘米为单位)分别表示10个苹果到地面的高度,两个相邻的整数之间用一个空格分隔。
第二行只包括一个100到120之间(包含100和120)的整数(以厘米为单位),表示小明把手伸直的时候能够达到的最大高度。

输出

包括一行,这一行只包含一个整数,表示小明能够摘到的苹果的数目。

来源/分类

样例输入

100 200 150 140 129 134 167 198 200 111
110

样例输出

5

思路:苹果高度 ≤ 手高 + 板凳高 即可摘到,逐个计数。

复杂度:O(n)

参考代码:

// 1093 摘苹果
// 10 个苹果,小明手伸直高度 h,踩 30cm 板凳后可够到 h+30
// 苹果高度 <= h+30 即可摘到(碰到就掉)
#include <bits/stdc++.h>
using namespace std;

int main() {
int apple[10];
for (int i = 0; i < 10; i++) scanf("%d", &apple[i]);
int h;
scanf("%d", &h);
int reach = h + 30, cnt = 0;
for (int i = 0; i < 10; i++)
if (apple[i] <= reach) cnt++;
printf("%d\\n", cnt);
return 0;
}


1094 校门外的树

题面

1094 校门外的树

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

某校大门外长度为L的马路上有一排树,每两棵相邻的树间隔均为1米。可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置;数轴上的每个整数点,即0,1,2,……,L,都种有一棵树。由于马路上有一些区域要用来建地铁。这些区域用它们在数轴上的起始点和终止点表示。已知任一区域的起始点和终止点的坐标都是整数,区域之间可能有重合的部分。现在要把这些区域中的树(包括区域端点处的两棵树)移走。请计算将这些树都移走后,马路上还有多少棵树。

输入

第一行有两个整数L(1 ≤ L ≤ 10000)和 M(1 ≤ M ≤ 100),L代表马路的长度,M代表区域的数目,L和M之间用一个空格分隔。接下来的M行每行包含两个不同的整数,用一个空格分隔,表示一个区域的起始点和终止点的坐标。
对于20%的数据,区域之间没有重合的部分;对于其它的数据,区域之间有重合的情况。

输出

包括一行,这一行只包含一个整数,表示马路上剩余的树的数目。

来源/分类

样例输入

500 3
150 300
100 200
470 471

样例输出

298

思路:差分/标记:把每段砍树区间(含端点)打上标记,最后统计未被覆盖的树(共 L+1 棵)。

复杂度:O(L+m)

参考代码:

// 1094 校门外的树
// 数轴上 0..L 每个整数点一棵树,共 L+1 棵
// 移走 M 个区间(含两端点)内的树,区间可能重合,用标记数组统计剩余
#include <bits/stdc++.h>
using namespace std;

int main() {
int L, M;
if (scanf("%d %d", &L, &M) != 2) return 0;
vector<int> removed(L + 1, 0); // 0..L 共 L+1 个点
for (int i = 0; i < M; i++) {
int s, e;
scanf("%d %d", &s, &e);
if (s > e) swap(s, e);
if (s < 0) s = 0;
if (e > L) e = L;
for (int j = s; j <= e; j++) removed[j] = 1; // 端点处的树也要移走
}
int cnt = 0;
for (int j = 0; j <= L; j++)
if (!removed[j]) cnt++;
printf("%d\\n", cnt);
return 0;
}


1095 软件学院OJ

⚠️ 本题已被管理员停用:访问题目页只显示“题目当前不可用”,
题面与测试数据均不可见。下方代码仅供参考,无法验证是否 AC。

思路:题目已被管理员停用(页面提示「题目当前不可用」),题面与测试数据均不可见。

复杂度:—

参考代码:

// 1095 软件学院OJ
// 题面缺失:oj/raw/1095.html 是 HUSTOJ 的 "题目当前不可用" 页面,
// statements/1095.md 只有标题,没有题目描述/输入/输出/样例,无法据此写出正确解法。
// 占位文件,等待题面补齐后再实现。
#include <bits/stdc++.h>
using namespace std;

int main() {
return 0;
}


1096 相同数个数

题面

1096 相同数个数

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

输出一个整数序列中与指定数字相同的数的个数。
总时间限制: 1000 ms 内存限制: 65536 kB。

输入

输入包含三行:
第一行为N,表示整数序列的长度(N ≤ 100);
第二行为N个整数,整数之间以空格分隔;
第三行包含一个整数,为指定的整数m。

输出

输出为N个数中与m相同的数的个数。

来源/分类

样例输入

3
2 3 2
2

样例输出

2

思路:逐个比较,统计与给定值相同的元素个数。

复杂度:O(n)

参考代码:

// 1096 相同数个数
// 读入 N 个数,统计等于 m 的个数
#include <bits/stdc++.h>
using namespace std;

int main() {
int n;
if (scanf("%d", &n) != 1) return 0;
vector<int> a(n);
for (int i = 0; i < n; i++) scanf("%d", &a[i]);
int m;
scanf("%d", &m);
int cnt = 0;
for (int i = 0; i < n; i++)
if (a[i] == m) cnt++;
printf("%d\\n", cnt);
return 0;
}


1097 冰雹猜想

题面

1097 冰雹猜想

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

给出一个正整数n,然后对这个数字一直进行下面的操作:如果这个数字是奇数,那么将其乘3再加1,否则除以2。经过若干次循环后,最终都会回到1。经过验证,很大的数字(7×1011)都可以按照这样的方式变成1,所以被称为“冰雹猜想”。例如当n是20,变化的过程是20→10→5→16→8→4→2→1。根据给定的数字,验证这个猜想,并从最后的1 开始,倒序输出整个变化序列。

输入

输入一个正整数n。

输出

输出若干个由空格隔开的正整数,表示从最后的1开始倒序的变化数列。

提示

来源/分类

样例输入

20

样例输出

1 2 4 8 16 5 10 20

思路:冰雹猜想:奇数 3n+1、偶数 n/2,记录序列后倒序输出直到 1。

复杂度:O(步数)

参考代码:

// 1097 冰雹猜想
// 记录变化序列(含首项 n 与最后的 1),再倒序输出
#include <bits/stdc++.h>
using namespace std;

int main() {
long long n;
if (scanf("%lld", &n) != 1) return 0;
vector<long long> v;
v.push_back(n);
while (n != 1) {
if (n % 2 == 1)
n = n * 3 + 1;
else
n = n / 2;
v.push_back(n);
}
// 倒序输出:1 2 4 8 16 5 10 20,数之间一个空格,末尾换行
for (int i = (int)v.size() – 1; i >= 0; i—) {
if (i != (int)v.size() – 1) printf(" ");
printf("%lld", v[i]);
}
printf("\\n");
return 0;
}


1098 卡片游戏

题面

1098 卡片游戏

时间限制 1.000 sec / 内存限制 128 MiB

题目描述

小明有很多数字卡片,每张卡片上都是09中的一个数字。小明准备用这些卡片来拼一些数,他想从1开始拼出正整数,每拼一个,就保存起来,卡片就不能用来拼其它数了。小明想知道自己能从1拼到多少。例如,当小明有30张卡片,其中09各3张,则可以拼出1到10,但是拼11时卡片1已经只有一张了,不够拼出11。现在小明手里有0到9的卡片各n张,请问小明可以从1拼到多少?

输入

输入一个正整数n。

输出

小明可以从1拼到的最大数值。

来源/分类

样例输入

2021

样例输出

3181

思路:逐个数统计各数字的卡片需求,需求超过 30 张库存即停;注意 11 这种重复数字要一次扣两张 1。

复杂度:O(答案位数)

参考代码:

// 1098 卡片游戏
// 0~9 各 n 张,从 1 开始连续拼数,能拼出来就保存下来(卡片被消耗),
// 直到某个数拼不出为止,答案就是能拼到的最大整数。
// 注意:检查时要把该数里每个数字的“出现次数”一起扣减(例如 11 需要两张 1),
// 所以先用 need[] 统计各位数字的需求量,再统一判断与扣减。
#include <bits/stdc++.h>
using namespace std;

int main() {
long long n;
if (scanf("%lld", &n) != 1) return 0;

long long cnt[10];
for (int d = 0; d < 10; d++) cnt[d] = n;

long long ans = 0;
for (long long x = 1;; x++) {
long long need[10] = {0};
long long t = x;
while (t > 0) {
need[t % 10]++;
t /= 10;
}
bool ok = true;
for (int d = 0; d < 10; d++)
if (need[d] > cnt[d]) { ok = false; break; }
if (!ok) break; // 这个数拼不出来,停止
for (int d = 0; d < 10; d++) cnt[d] -= need[d];
ans = x;
}
printf("%lld\\n", ans);
return 0;
}


1099 整数位序

题面

1099 整数位序

时间限制 1.000 sec / 内存限制 64 MiB

题目描述

下面的图形是著名的杨辉三角形。
如果按从上到下、从左到右的顺序把所有数排成一列,可以得到如下数列:
1,1,1,1,2,1,1,3,3,1,1,4,6,4,1,…
给定一个正整数N,请你输出数列中第一次出现N是在第几个数?
总时间限制: 1000 ms 内存限制: 65536 kB。

输入

输入一个正整数N(N <= 5000)。

输出

输出一个整数代表答案。

来源/分类

样例输入

6

样例输出

13

思路:整数位序:从最高位到最低位逐位输出各位数字。

复杂度:O(位数)

参考代码:

// 1099 整数位序
// 杨辉三角按从上到下、从左到右拉直成数列:
// 1 | 1 1 | 1 2 1 | 1 3 3 1 | 1 4 6 4 1 | …
// 第 i 行(从 0 计)有 i+1 个数,行内第 j 个(从 0 计)的值为 C(i,j),
// 而该行第 1 个数在数列中的序号为 i*(i+1)/2 + 1,所以
// pos(i,j) = i*(i+1)/2 + j + 1
// 校验:C(4,2)=6 -> 10+2+1=13(与样例一致);C(2,1)=2 -> 3+1+1=5;
// C(8,4)=70 -> 36+4+1=41;C(5,2)=10 -> 15+2+1=18。
// 利用对称性 C(i,j)=C(i,i-j),只需考虑 j <= i/2 的列。
// 固定 j 时 C(i,j) 关于 i 单调递增,逐列找第一次等于 N 的位置即可,
// j 从 1 开始枚举,直到该列最小值 C(2j,j) 已经大于 N 为止
// (N<=5000 时只需查到 j=6,因为 C(12,6)=924、C(14,7)=3432、C(16,8)=12870>5000)。
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

ll solve(ll N) {
if (N == 1) return 1; // 第 0 行第 0 个,数列中的第 1 个数

// N 必然出现在第 N 行(C(N,1)=C(N,N-1)=N,位于行内下标 1 处),作为初始上界
ll best = N * (N + 1) / 2 + 2;

for (ll j = 1; j <= 12; j++) {
ll c = 1; // C(j,j) = 1,从 i = j 开始枚举
for (ll i = j;; i++) {
if (c == N) {
ll pos = i * (i + 1) / 2 + j + 1; // C(i,j) 在数列中的序号
if (pos < best) best = pos;
break; // 该列单调递增,第一个相等的位置就是本列最优
}
if (c > N) break; // 后面只会更大,本列无解
// 递推 C(i+1,j) = C(i,j) * (i+1) / (i+1-j)
ll num = c * (i + 1), den = i + 1 – j;
if (num % den != 0) break; // 理论上不会发生,保险处理
ll nxt = num / den;
if (nxt > N) break; // 已超过 N,本列不会再有等于 N 的值
c = nxt;
}
// 第 j 列的最小值是 C(2j,j)(该列关于 i 对称,此处取到最小值);
// 若它已经大于 N,则更大的 j 的列最小值更大,可以安全停止
ll mid = 1;
bool tooBig = false;
for (ll t = 1; t <= j; t++) {
mid = mid * (j + t) / t;
if (mid > N) { tooBig = true; break; }
}
if (tooBig) break;
}
return best;
}

int main() {
ll N;
if (scanf("%lld", &N) != 1) return 0;
printf("%lld\\n", solve(N));
return 0;
}


赞(0)
未经允许不得转载:网硕互联帮助中心 » HAUE软件学院OJ题解汇总_第2篇_1050-1099
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!