习题 10-1 砌砖 Add bricks in the wall
题目描述了一个有9层的砖墙金字塔。规则很简单:每个砖块上的数字,等于它下方支撑的两个砖块数字之和。题目只给出了所有奇数行中,奇数位置上的数字(比如第1行第1个,第3行第1个、第3个......),要求我们求出墙上所有砖块的数字,并且保证有唯一解。
思路
由于每一块砖上被标识的整数是其下面两块砖上的整数之和,所以,对于三角形墙中的任何一个三角形:
第一行:c
第二行:a+x,x+b
第三行:a,x,b
其中,位于奇数行奇数位置的 a,b,c 已知,则有 c=(a+x)+(b+x),则 x=2c−a−b。
由此可知:
-
首先计算位于奇数行偶数位置的元素值 x。
-
然后计算出位于偶数行的元素值。
cpp
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[9][9];
int main() {
int t;
cin >> t;
while (t--) {
for (int i = 0; i < 9; i++) {
for (int j = 0; j <= i; j += 2) {
cin >> a[i][j];
}
}
for (int i = 8; i > 0; i-= 2) {
for (int j = 1; j < i; j += 2) {
a[i][j] = (a[i - 2][j - 1] - a[i][j - 1] - a[i][j + 1]) / 2;
}
}
for (int i = 1; i < 9; i += 2) {
for (int j = 0; j <= i; j++) {
a[i][j] = a[i + 1][j] + a[i + 1][j + 1];
}
}
for (int i = 0; i < 9; i++) {
for (int j = 0; j <= i; j++) {
cout << a[i][j] << " ";
}
cout << "\n";
}
}
return 0;
}
习题 10-9 约数 Divisors
给定 n 个区间 [l,r],求出每个区间内约数个数最大的数。
数据范围:1⩽l<r⩽1010,r−l⩽104。
需要了解 约数个数定理
习题 10-17 H-半素数 Semi-prime H-numbers
给你一个由 4n+1 的数组成的集合,该集合中的数被称为 H 数,集合中的素数是 H− 素数, 两个 H− 素数的乘积组成的数被称为H− 合成数,现在给定一些 h ,求 [0,h] 中的 H− 合成数的个数。
解:我这个看了好久才看题解弄明白,这里我就直接放我认为详细清晰的了。
习题 10-22 飞机环球 Planes around the World
这道题没翻译,我用AI简化翻译的:
-
问题背景 :飞机从A点出发,油箱满油可飞
a/b圈(即全球周长的a/b)。飞机之间可在瞬间互相加油(但不能超过油箱容量)。目标是让至少一架飞机成功环球飞行(飞完1圈)并返回起点,同时所有参与飞机最终都能安全返回A点。 -
输入与输出 :输入多组
a和b,输出达到目标所需的最少飞机总数。如果无解(需求超过一万架),则输出-1。 -
关键限制条件 :题目为了简化,给出了特定的调度规则(你提供的图2是
a=1, b=2时需要5架的经典案例),这直接引导了我们的解题方向。
解:
首先考虑正向飞行的飞机,我们仿照样例中的走法,考虑n架飞机正向飞行的情况(包括一号飞机),题目中要求一架飞机需要给其它飞机加相同的油,所以我们每次都让一架飞机把其它飞机的油加满,然后该飞机返回起点。为了便于考虑,我们设飞机初始携带的油量为 a/b ,在上面的要求下,我们发现每次正向飞行的飞机都可以前行 a/b × 1/(n+1) ,总共有n架飞机,前n−1次飞行,都会前进相同的距离,即 a/b × 1/(n+1) ,同时每次少一架飞机返回起点,直至剩余一架飞机,前进 a/b ,所以正向行驶 a/b × (n-1)/(n+1) + a/b ,显然,我们发现,如果 a/b 小于等于 1/3 ,是无法完成旅行的,因为反向飞行的飞机无法接应。
对于反向的飞机,采用相似的想法,但是注意此时应该保证每架飞机的油量相同,以便可以一起飞到下一个反向飞机处接应。
cpp
#include <bits/stdc++.h>
using namespace std;
int cal(int a,int b)
{
if(b >= 3*a) return -1;
int Min = 10000;
double dis = 0.0,A=a,B=b;
for(int i=1;i <= Min; i++){
dis = 0.0;
dis = dis + double(i-1)/double(i+1) * (A/B) + A/B;
int m=1;
while(dis < (1-(1e-6)))
{
dis = dis + ((A/B) - (1 - dis)) / (m+1);
if(m+i>Min) break;
m++;
}
Min = min(m+i-1,Min);
}
return Min;
}
int main()
{
int a,b,T,cnt=1;
cin >> T;
while(T--){
cin >> a >> b;
cout <<"Case " << cnt <<": " <<cal(a,b) << endl;
cnt++;
}
return 0;
}