@[TOC]
分析:
本人今年大一刚接触acm拿了个省三,本来能省二的题目交错,啊啊啊啊啊到了最后一份中才发现改都改不了了错失省二明年加油,但我同学有的省一膜拜膜拜;
@[top]
# 填空题
##1 进制转换
问题描述】
九进制正整数
9进制转换成十进制等于多少?
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
题解
经典进制转换
print(2 + 2 * 9 + 0 * 9 * 9 + 2 * 9 * 9 * 9)
答案 1478
# B 顺子日期 (5分)
【问题描述】
小明特别喜欢顺子。顺子指的就是连续的三个数字:123 123123、456 456456 等。顺子日期指的就是在日期的 y y y y m m d d yyyymmddyyyymmdd 表示法中,存在任意连续的三位数是一个顺子的日期。例如 20220123 2022012320220123 就是一个顺子日期,因为它出现了一个顺子:123 123123;而 20221023 2022102320221023 则不是一个顺子日期,它一个顺子也没有。小明想知道在整个 2022 20222022 年份中,一共有多少个顺子日期。
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。
分析:
012算是顺子日期但是210不算
答案 4/14(不知道是哪个但好像14更对);
C 刷题统计 (10分)
【问题描述】
小明决定从下周一开始努力刷题准备蓝桥杯竞赛。他计划周一至周五每天做 a aa 道题目,周六和周日每天做 b bb 道题目。请你帮小明计算,按照计划他将在第几天实现做题数大于等于 n nn 题?【输入格式】
输入一行包含三个整数 a aa, b bb 和 n nn.【输出格式】
输出一个整数代表天数。【样例输入】
10 20 99
1
【样例输出】8
1
【评测用例规模与约定】
对于 50 % 50\%50% 的评测用例,1 ≤ a , b , n ≤ 1 0 6 1 ≤ a, b, n ≤ 10^61≤a,b,n≤10
6
.
对于 100 % 100\%100% 的评测用例,1 ≤ a , b , n ≤ 1 0 18 1 ≤ a, b, n ≤ 10^{18}1≤a,b,n≤10
18
思路:n的数据范为非常大,不能通过遍历每一个数将其相加来计算,所以我们应该算出一周的总刷题量,用总刷体谅/每一周的刷题量计算出要几周,取余的数一天一天遍历即可;
#include<bits/stdc++.h>
using namespace std;
long long int a,b,c,s,n,m;
int main(){
cin>>a>>b>>c;
n=5*a+2*b;
m=c%n;s=c/n*7;
int i=0;
while(m>0){
++i;
if(i>5){
m=m-b;
}
else m=m-a;
s++;
}
printf("%lld",s);
}
D 修剪灌木 (10分)
【问题描述】
爱丽丝要完成一项修剪灌木的工作。
有 N NN 棵灌木整齐的从左到右排成一排。爱丽丝在每天傍晚会修剪一棵灌木,让灌木的高度变为 0 00 厘米。爱丽丝修剪灌木的顺序是从最左侧的灌木开始,每天向右修剪一棵灌木。当修剪了最右侧的灌木后,她会调转方向,下一天开始向左修剪灌木。直到修剪了最左的灌木后再次调转方向。然后如此循环往复。
灌木每天从早上到傍晚会长高 1 11 厘米,而其余时间不会长高。在第一天的早晨,所有灌木的高度都是 0 00 厘米。爱丽丝想知道每棵灌木最高长到多高。【输入格式】
一个正整数 N NN,含义如题面所述。【输出格式】
输出 N NN 行,每行一个整数,第 i ii 行表示从左到右第 i ii 棵树最高能长到多高。【样例输入】
3
1
【样例输出】4
2
4
1
2
3
【评测用例规模与约定】
对于 30 % 30\%30% 的数据,N ≤ 10 N ≤ 10N≤10.
对于 100 % 100\%100% 的数据,1 < N ≤ 10000 1 < N ≤ 100001<N≤10000.
思路:
通过计算案例的组成发现该题是有规律的,规律就是max(i-1,n-i)的值;
#include<bits/stdc++.h>
using namespace std;
const int r=100010;
int n,s;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
int c=max(i-1,n-i)*2;
printf("%d\n",c);
}
}
E X 进制减法 (15分)
【问题描述】
进制规定了数字在数位上逢几进一。
X XX 进制是一种很神奇的进制,因为其每一数位的进制并不固定!例如说某种 X XX 进制数,最低数位为二进制,第二数位为十进制,第三数位为八进制,则 X XX 进制数 321 321321 转换为十进制数为 65 6565。
现在有两个 X XX 进制表示的整数 A AA 和 B BB,但是其具体每一数位的进制还不确定,只知道 A AA 和 B BB 是同一进制规则,且每一数位最高为 N NN 进制,最低为二进制。请你算出 A − B A − BA−B 的结果最小可能是多少。
请注意,你需要保证 A AA 和 B BB 在 X XX 进制下都是合法的,即每一数位上的数字要小于其进制。【输入格式】
第一行一个正整数 N NN,含义如题面所述。
第二行一个正整数 M a M_aM
a
,表示 X XX 进制数 A AA 的位数。
第三行 M a M_aM
a
个用空格分开的整数,表示 X XX 进制数 A AA 按从高位到低位顺序各个数位上的数字在十进制下的表示。
第四行一个正整数 M b M_bM
b
,表示 X XX 进制数 B BB 的位数。
第五行 M b M_bM
b
个用空格分开的整数,表示 X XX 进制数 B BB 按从高位到低位顺序各个数位上的数字在十进制下的表示。
请注意,输入中的所有数字都是十进制的。【输出格式】
输出一行一个整数,表示 X XX 进制数 A − B A − BA−B 的结果的最小可能值转换为十进制后再模 1000000007 10000000071000000007 的结果。【样例输入】
11
3
10 4 0
3
1 2 0
1
2
3
4
5
【样例输出】94
1
【样例说明】
当进制为:最低位 2 进制,第二数位 5 进制,第三数位 11 进制时,减法得到的差最小。此时 A 在十进制下是 108 ,B 在十进制下是 14 ,差值是 94
题解
X XX 进制数 321 321321 是如何转换为十进制数 65 6565 的:
最低数位为二进制,十进制为 1 ∗ 1 1 * 11∗1;
第二数位为十进制,十进制为 2 ∗ 2 2 * 22∗2;
第三数位为八进制,十进制为 3 ∗ 2 ∗ 10 3 * 2 * 103∗2∗10;
加起来即为 65 6565 。
每一位的进制要尽可能小。
进制最小的时候所取得差值最小;
#include<bits/stdc++.h> using namespace std; const int r=1000010; const int w=1000000007; int a[r],b[r];long long int n,n1,m1,m,s,res,p[r],aa[r],bb[r],s1,s2; long long int mul[r]; int main(){ cin>>n; cin>>n1; for(int i=n1;i>=1;i--){ cin>>a[i]; } cin>>m1; for(int i=m1;i>=1;i--) cin>>b[i]; for(int i=n1;i>=1;i--){ p[i]=max(a[i],b[i])+1; if(p[i]<2)p[i]=2; }mul[1]=1; for(int i=2;i<=n1;i++){ mul[i]=p[i-1]*mul[i-1]%w; } for(int i=n1;i>=1;i--){ s1=(s1+a[i]*mul[i])%w; } for(int i=m1;i>=1;i--){ s2=(s2+b[i]*mul[i])%w; } printf("%d",(s1-s2+w)%w); }
F 统计子矩阵 (15分)
【问题描述】
给定一个 N × M N × MN×M 的矩阵 A AA,请你统计有多少个子矩阵(最小 1 × 1 1 × 1,最大 N × M N × M) 满足子矩阵中所有数的和不超过给定的整数 K ?【输入格式】
第一行包含三个整数 N , M 和 K .
之后 N 行每行包含 M 个整数,代表矩阵 A【输出格式】
一个整数代表答案。【样例输入】
3 4 10
1 2 3 4
5 6 7 8
9 10 11 12
1
2
3
4
【样例输出】19
1
【样例说明】
满足条件的子矩阵一共有 19 1919,包含:
大小为 1 × 1 的有 10 1个。
大小为 1 × 2 的有 3 个。
大小为 1 × 3的有 2 个。
大小为 1 × 1 × 4的有 1 个。
大小为 2 × 1 的有 3 个。
该题思路:
使用前缀和进行计算出来值,计算出每一个区间的前缀和判断是否满足题目条件;
只能得70%的分
#include <bits/stdc++.h>
#define ll long long
#define N 502
using namespace std;
int n, m, k;
int a[N][N], sum[N][N];
ll ans = 0;
int main() {
scanf("%d%d%d", &n, &m, &k);
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
scanf("%d", &a[i][j]);
}
}
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
sum[i][j] =
a[i][j] + sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1];
}
}
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
for (int x = i; x <= n; ++x) {
for (int y = j; y <= m; ++y) {
if (sum[x][y] - sum[x][j - 1] - sum[i - 1][y] +
sum[i - 1][j - 1] <=
k) {
++ans;
}
}
}
}
}
printf("%lld\n", ans);
return 0;
}
G 积木画 (20分)
【问题描述】
小明最近迷上了积木画,有这么两种类型的积木,分别为 I 型(大小为 2
个单位面积)和 L 型(大小为 3 个单位面积):
同时,小明有一块面积大小为 2 × N 的画布,画布由 2 × N 个 1 × 1 区域构
成。小明需要用以上两种积木将画布拼满,他想知道总共有多少种不同的方式?
积木可以任意旋转,且画布的方向固定。
【输入格式】
输入一个整数 N,表示画布大小。
【输出格式】
输出一个整数表示答案。由于答案可能很大,所以输出其对 1000000007 取
模后的值
【样例输入】
3
【样例输出】
5
思路: dp状态压缩现在还不太会复制一个学长代码
#include<bits/stdc++.h>
#define N 10000007
using namespace std;
int n;
const int mod = 1000000007;
int dp[N][4];
int main() {
scanf("%d", &n);
dp[1][0] = dp[1][3] = 1;
for(int i = 2; i <= n; ++i) {
dp[i][0] = dp[i-1][3];
dp[i][1] = (dp[i-1][2] + dp[i-1][0]) % mod;
dp[i][2] = (dp[i-1][1] + dp[i-1][0]) % mod;
dp[i][3] = ((dp[i-1][0] + dp[i-1][1]) % mod + (dp[i-1][2] + dp[i-1][3]) % mod) % mod;
}
printf("%d\n", dp[n][3]);
return 0;
}
H 扫雷 (20分)
【问题描述】
小明最近迷上了一款名为《扫雷》的游戏。其中有一个关卡的任务如下,在一个二维平面上放置着 n nn 个炸雷,第 i ii 个炸雷 ( x i , y i , r i ) (x_i, y_i, r_i)(x
的一个圆。
为了顺利通过这片土地,需要玩家进行排雷。玩家可以发射 m mm 个排雷火箭,小明已经规划好了每个排雷火箭的发射方向,第 j jj 个排雷火箭 ( x j , y j , r j ) (x_j, y_j, r_j)(x
的一个圆,在其爆炸范围内的炸雷会被引爆。同时,当炸雷被引爆时,在其爆炸范围内的炸雷也会被引爆。现在小明想知道他这次共引爆了几颗炸雷?
你可以把炸雷和排雷火箭都视为平面上的一个点。一个点处可以存在多个炸雷和排雷火箭。当炸雷位于爆炸范围的边界上时也会被引爆。
【输入格式】
输入的第一行包含两个整数 n nn、m mm
【输出格式】
输出一个整数表示答案。
【样例输入】
2 1
2 2 4
4 4 2
0 0 5
1
2
3
4
【样例输出】
2
1
【样例说明】
只会暴力bfs骗粉
#include<iostream>
#include<cmath>
using namespace std;
int n, m;
int grid[5000][5000];
struct node {
int x, y, r;
node() {
}
node(int _x, int _y, int _r) {
x = _x;
y = _y;
r = _r;
}
}no[50001];
void input() {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> no[i].x >> no[i].y >> no[i].r;
}
for (int i = n+1; i <= n+m; i++) {
cin >> no[i].x >> no[i].y >> no[i].r;
}
}
double dis(int i, int j) {
return sqrt((no[i].x - no[j].x) * (no[i].x - no[j].x) + (no[i].y - no[j].y) * (no[i].y - no[j].y));
}
int cnt = 0;
void dfs(int n) {
for (int i = 1; i <= n + m; i++) {
if (grid[n][i] == 1 && n != i) {
grid[n][i] =grid[i][n]=0;
cnt++;
dfs(i);
}
}
}
int main() {
input();
for (int i = 1; i <= n+m; i++) {
for (int j = 1; j <= n+m; j++) {
if (dis(i, j)<=no[i].r) {
grid[i][j]=1;
}
}
}
for (int i = n + 1; i <= n + m; i++) {
dfs(i);
}
cout << cnt;
}