练习题
P8627 [蓝桥杯 2015 省 A] 饮料换购
# [蓝桥杯 2015 省 A] 饮料换购
## 题目描述
乐羊羊饮料厂正在举办一次促销优惠活动。乐羊羊 C 型饮料,凭 $3$ 个瓶盖可以再换一瓶 C 型饮料,并且可以一直循环下去(但不允许暂借或赊账)。
请你计算一下,如果小明不浪费瓶盖,尽量地参加活动,那么,对于他初始买入的 $n$ 瓶饮料,最后他一共能喝到多少瓶饮料。
## 输入格式
一个整数 $n$,表示开始购买的饮料数量。($0<n<10000$)
## 输出格式
一个整数,表示实际得到的饮料数。
## 样例 #1
### 样例输入 #1
```
100
```
### 样例输出 #1
```
149
```
## 样例 #2
### 样例输入 #2
```
101
```
### 样例输出 #2
```
151
```
## 提示
2015 年蓝桥杯省赛 A 组 H 题。
主要是每次换的一次饮料,就要重新加入到n中。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin >> n;
int sum = n;
while (n > 2)
{
sum += n / 3;
n = n / 3 + n % 3;
}
cout << sum;
}
P8673 [蓝桥杯 2018 国 C] 迷宫与陷阱
# [蓝桥杯 2018 国 C] 迷宫与陷阱
## 题目描述
小明在玩一款迷宫游戏,在游戏中他要控制自己的角色离开一间由 $N \times N$ 个格子组成的二维迷宫。
小明的起始位置在左上角,他需要到达右下角的格子才能离开迷宫。
每一步,他可以移动到上下左右相邻的格子中(前提是目标格子可以经过)。
迷宫中有些格子小明可以经过,我们用 `.` 表示;
有些格子是墙壁,小明不能经过,我们用 `#` 表示。
此外,有些格子上有陷阱,我们用 `X` 表示。除非小明处于无敌状态,否则不能经过。
有些格子上有无敌道具,我们用 `%` 表示。
当小明第一次到达该格子时,自动获得无敌状态,无敌状态会持续 $K$ 步。
之后如果再次到达该格子不会获得无敌状态了。
处于无敌状态时,可以经过有陷阱的格子,但是不会拆除 / 毁坏陷阱,即陷阱仍会阻止没有无敌状态的角色经过。
给定迷宫,请你计算小明最少经过几步可以离开迷宫。
## 输入格式
第一行包含两个整数 $N$ 和 $K$。$(1 \le N \le 1000,1 \le K \le 10)$。
以下 $N$ 行包含一个 $N\times N$ 的矩阵。
矩阵保证左上角和右下角是 `.`。
## 输出格式
一个整数表示答案。如果小明不能离开迷宫,输出 $-1$。
## 样例 #1
### 样例输入 #1
```
5 3
...XX
##%#.
...#.
.###.
.....
```
### 样例输出 #1
```
10
```
## 样例 #2
### 样例输入 #2
```
5 1
...XX
##%#.
...#.
.###.
.....
```
### 样例输出 #2
```
12
```
## 提示
时限 3 秒, 256M。蓝桥杯 2018 年第九届国赛
#include<bits/stdc++.h>
using namespace std;
const int N = 1e3 + 5;
int n, k;
char g[N][N];
int vis[N][N];
struct node
{
int x, y, step, magic;
};
int dxy[4][2] = { {1,0},{-1,0},{0,1},{0,-1} };
int main()
{
cin >> n >> k;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
cin >> g[i][j];
}
}
memset(vis, -1, sizeof vis);
queue<node> q;
vis[1][1] = 0;
q.push({ 1,1,0,0 });
while (q.size())
{
node t = q.front();
q.pop();
if (t.x == n && t.y == n)
{
cout << t.step;
return 0;
}
for (int i = 0; i < 4; i++)
{
int tx = t.x + dxy[i][0];
int ty = t.y + dxy[i][1];
if (g[tx][ty] == 'X' && t.magic == 0)
continue;
int magic = max(0, t.magic - 1);
if (g[tx][ty] == '%')
magic = k;
if (tx >= 1 && tx <= n && ty >= 1 && ty <= n && vis[tx][ty] < magic && g[tx][ty] != '#')
{
vis[tx][ty] = magic;
q.push({ tx,ty,t.step + 1,magic });
}
}
}
cout << -1;
return 0;
}
P8783 [蓝桥杯 2022 省 B] 统计子矩阵
# [蓝桥杯 2022 省 B] 统计子矩阵
## 题目描述
给定一个 $N \times M$ 的矩阵 $A$,请你统计有多少个子矩阵 (最小 $1 \times 1$, 最大 $N \times M)$ 满足子矩阵中所有数的和不超过给定的整数 $K$。
## 输入格式
第一行包含三个整数 $N, M$ 和 $K$。
之后 $N$ 行每行包含 $M$ 个整数, 代表矩阵 $A$。
## 输出格式
一个整数代表答案。
## 样例 #1
### 样例输入 #1
```
3 4 10
1 2 3 4
5 6 7 8
9 10 11 12
```
### 样例输出 #1
```
19
```
## 提示
**【样例说明】**
满足条件的子矩阵一共有 $19$,包含:
大小为 $1 \times 1$ 的有 $10$ 个。
大小为 $1 \times 2$ 的有 $3$ 个。 大小为 $1 \times 3$ 的有 $2$ 个。
大小为 $1 \times 4$ 的有 $1$ 个。
大小为 $2 \times 1$ 的有 $3$ 个。
**【评测用例规模与约定】**
对于 $30 \%$ 的数据, $N, M \leq 20$.
对于 $70 \%$ 的数据, $N, M \leq 100$.
对于 $100 \%$ 的数据, $1 \leq N, M \leq 500,0 \leq A_{i j} \leq 1000,1 \leq K \leq 2.5\times10^8$.
蓝桥杯 2022 省赛 B 组 F 题。
#include<bits/stdc++.h>
using namespace std;
#define int long long
int a[1000][1000], s[1000][1000];
int b[1000];
signed main()
{
int n, m, k, ans = 0;
cin >> n >> m >> k;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
cin >> a[i][j];
}
}
for (int j = 1; j <= m; j++)
{
for (int i = 1; i <= n; i++)
{
s[i][j] = s[i - 1][j] + a[i][j];
}
}
for (int ii = 1; ii <= n; ii++)
{
for (int i = ii; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
b[j] = s[i][j] - s[ii - 1][j];
}
int L = 1, R = 0, sum = 0;
while (R < m)
{
R++;
sum += b[R];
if (sum <= k)
ans += (R - L + 1);
else
{
while (sum > k)
{
sum -= b[L];
L++;
}
ans += (R - L + 1);
}
}
}
}
cout << ans;
return 0;
}
P1934 封印
# 封印
## 题目背景
很久以前,魔界大旱,水井全部干涸,温度也越来越高。为了拯救居民,夜叉族国王龙溟希望能打破神魔之井,进入人界“窃取”水灵珠,以修复大地水脉。可是六界之间皆有封印,神魔之井的封印由蜀山控制,并施有封印。龙溟作为魔界王族,习有穿行之术,可任意穿行至任何留有空隙的位置。然而封印不留有任何空隙! 龙溟无奈之下只能强行破除封印。破除封印必然消耗一定的元气。为了寻找水灵珠,龙溟必须减少体力消耗。他可以在破除封印的同时使用越行术。
## 题目描述
神魔之井的封印共有 $n$ 层,每层封印都有一个坚固值。身为魔族的龙溟单独打破一层封印时需要消耗的元气为该层封印的坚固值和封印总层数 $n$ 的平方的乘积; 但他也可以打破第 i 层到第 j 层之间的所有封印( $i<j$),总元气消耗为第 $i,j$ 层封印的坚固值之和与第 $i,j$ 层之间所有封印层(包括第 $i,j$ 层)的坚固值之和的乘积,但为了不惊动蜀山,第 $i,j$ 层封印的坚固值之和不能大于 $t$ (单独打破可以不遵守)。
## 输入格式
第一行包含两个正整数 $n$ 和 $t$。
第二行有 $n$ 个正整数,第 $i$ 个数为 $a_i$,表示第 $i$ 层封印的坚固值。
## 输出格式
仅一行,包含一个正整数,表示最小消耗元气。
## 样例 #1
### 样例输入 #1
```
6 10
8 5 7 9 3 5
```
### 样例输出 #1
```
578
```
## 提示
#### 样例解释
先单独打破第一层,再用越行术从第二层直接打破到最后一层。 这样消耗元气 $8 \times 6^2 + (5 + 5) \times (5 + 7 + 9 + 3 + 5) = 578$。
#### 数据范围
对于 $10\%$ 的数据, $n\le10$;
对于 $50\%$ 的数据, $n\le100$;
对于 $70\%$ 的数据, $n\le500$;
对于 $100\%$ 的数据, $n\le1000$, $a_i(1 \le i \le n) , t \le 20000$。
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n, t;
int a[10000] = { 0 };
int f[10000] = { 0 };
int sum[10000] = { 0 };
signed main()
{
cin >> n >> t;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
sum[i] = sum[i - 1] + a[i];
f[i] = 10000000009;
}
for (int i = 1; i <= n; i++)
{
f[i] = min(f[i], f[i - 1] + a[i] * n * n);
for (int j = 1; j < i; j++)
{
if (a[i] + a[j] <= t)
{
f[i] = min(f[i], f[j - 1] + (a[j] + a[i]) * (sum[i] - sum[j - 1]));
}
}
}
cout << f[n];
return 0;
}
P2759 奇怪的函数
# 奇怪的函数
## 题目描述
使得 $x^x$ 达到或超过 $n$ 位数字的最小正整数 $x$ 是多少?
## 输入格式
一个正整数 $n$。
## 输出格式
使得 $x^x$ 达到 $n$ 位数字的最小正整数 $x$。
## 样例 #1
### 样例输入 #1
```
11
```
### 样例输出 #1
```
10
```
## 提示
对于全部数据,$1\le n\le 2\times 10^9$。
#include<bits/stdc++.h>
using namespace std;
int n, l = 1, r = 3e8, m;
int main()
{
cin >> n, n--;
while (l < r)
{
m = (l + r) / 2;
if (m * log10(m) < n)
l = m + 1;
else
r = m;
}
cout << l;
}
P1455 搭配购买
# 搭配购买
## 题目描述
明天就是母亲节了,电脑组的小朋友们在忙碌的课业之余挖空心思想着该送什么礼物来表达自己的心意呢?听说在某个网站上有卖云朵的,小朋友们决定一同前往去看看这种神奇的商品,这个店里有 $n$ 朵云,云朵已经被老板编号为 $1,2,3,...,n$,并且每朵云都有一个价值,但是商店的老板是个很奇怪的人,他会告诉你一些云朵要搭配起来买才卖,也就是说买一朵云则与这朵云有搭配的云都要买,电脑组的你觉得这礼物实在是太新奇了,但是你的钱是有限的,所以你肯定是想用现有的钱买到尽量多价值的云。
## 输入格式
第一行输入三个整数,$n,m,w$,表示有 $n$ 朵云,$m$ 个搭配和你现有的钱的数目。
第二行至 $n+1$ 行,每行有两个整数, $c_i,d_i$,表示第 $i$ 朵云的价钱和价值。
第 $n+2$ 至 $n+1+m$ 行 ,每行有两个整数 $u_i,v_i$。表示买第 $u_i$ 朵云就必须买第 $v_i$ 朵云,同理,如果买第 $v_i$ 朵就必须买第 $u_i$ 朵。
## 输出格式
一行,表示可以获得的最大价值。
## 样例 #1
### 样例输入 #1
```
5 3 10
3 10
3 10
3 10
5 100
10 1
1 3
3 2
4 2
```
### 样例输出 #1
```
1
```
## 提示
- 对于 $30\%$ 的数据,满足 $1 \le n \le 100$;
- 对于 $50\%$ 的数据,满足 $1 \le n, w \le 10^3$,$1 \le m \le 100$;
- 对于 $100\%$ 的数据,满足 $1 \le n, w \le 10^4$,$0 \le m \le 5 \times 10^3$。
#include<bits/stdc++.h>
using namespace std;
int n, m, w;
int f[10000000], val[10000000], rmb[10000000];
int dp[10000000];
int getf(int v) //压缩路径
{
if (f[v] == v)
return v;
else
{
f[v] = f[getf(f[v])];
return f[v];
}
}
void merge(int u,int v) //合并
{
int t1 = 0, t2 = 0;
t1 = getf(v);
t2 = getf(u);
if (t1 != t2)
{
f[t2] = t1;
rmb[t1] += rmb[t2];
val[t1] += val[t2];
}
return;
}
int main()
{
cin >> n >> m >> w;
for (int i = 1; i <= n; i++)
{
f[i] = i;
cin >> rmb[i] >> val[i];
}
for (int i = 1; i <= m; i++)
{
int x, y;
cin >> x >> y;
merge(x, y);
}
int f0 = 0, f1 = 0, New_f = 0;
for (int i = 1; i <= n; i++)
{
if(f[i]==i)
for (int j = w; j >= rmb[i]; j--)
{
New_f = max(f1, f0 + val[i]);
f0 = f1;
f1 = New_f;
}
}
cout << f1;
return 0;
}