2024.07.03 题目整理
题目描述
唐克老师有一个用于存放羊腿的神奇装置,这个装置呈一个桶的形状,深度无限大,其中每一层都可以存放一个羊腿
每次唐克老师往桶里放入羊腿时,只能放在最顶层羊腿的更上一层,而每次取出羊腿时也只能取出最顶层的羊腿
例如唐克老师的桶里依次存放了 3 个羊腿,质量分别为 1,2,3,那么此时唐克老师只能取出最顶层质量为 3 的羊腿,不能跨过 3 直接取质量为 2 和 1 的羊腿
现在唐克老师给这个装置加了三个更加神奇的功能——生成、合成与复制!
1. 生成功能:唐克老师可以凭空生成一个质量为 1 的羊腿,并将它放在装置最顶层
2. 合成功能:唐克老师可以将现在处于最顶层的两个羊腿合并成一个羊腿,并且羊腿质量不会发生消耗,并将合成后的羊腿放在装置最顶层
3. 复制功能:唐克老师可以将现在处于最顶层的羊腿完美复制一份,并将它放在装置最顶层
例如唐克老师可以依次使用如下按钮:`生成、生成、合成、复制、生成、合成、合成`
这样的操作可以凭空得到一个质量为 5 的羊腿
假设三种功能的能量消耗均一样,现在唐克老师想知道最少需要使用多少次功能,可以凭空得到一个质量为 n 的羊腿?
并且唐克老师不想浪费粮食,他不希望最终装置中还存在其他羊腿
每次唐克老师往桶里放入羊腿时,只能放在最顶层羊腿的更上一层,而每次取出羊腿时也只能取出最顶层的羊腿
例如唐克老师的桶里依次存放了 3 个羊腿,质量分别为 1,2,3,那么此时唐克老师只能取出最顶层质量为 3 的羊腿,不能跨过 3 直接取质量为 2 和 1 的羊腿
现在唐克老师给这个装置加了三个更加神奇的功能——生成、合成与复制!
1. 生成功能:唐克老师可以凭空生成一个质量为 1 的羊腿,并将它放在装置最顶层
2. 合成功能:唐克老师可以将现在处于最顶层的两个羊腿合并成一个羊腿,并且羊腿质量不会发生消耗,并将合成后的羊腿放在装置最顶层
3. 复制功能:唐克老师可以将现在处于最顶层的羊腿完美复制一份,并将它放在装置最顶层
例如唐克老师可以依次使用如下按钮:`生成、生成、合成、复制、生成、合成、合成`
这样的操作可以凭空得到一个质量为 5 的羊腿
假设三种功能的能量消耗均一样,现在唐克老师想知道最少需要使用多少次功能,可以凭空得到一个质量为 n 的羊腿?
并且唐克老师不想浪费粮食,他不希望最终装置中还存在其他羊腿
输入
输入第一行包含一个整数 , 表示询问次数
每行包含一个正整数 ,表示唐克老师想要得到的羊腿质量
每行包含一个正整数 ,表示唐克老师想要得到的羊腿质量
输出
对于每一次询问,输出唐克老师最少需要使用功能的次数
样例输入 Copy
1
5
样例输出 Copy
7
提示

#include <bits/stdc++.h> using namespace std; using ll = long long; const int N = 1e5 + 10; ll t, n, stk[N], ans[N], mn, sum, idx; void dfs(ll step) { /* 剪枝 */ if (sum == n) { mn = min(mn, step + idx - 1); /* 当前已经执行step步,剩余的idx个元素 需要用idx-1步来进行合并, 故总步数为step + idx - 1; */ return; } if (step + idx - 1 >= mn or sum > n) { /* 当前步数已经不可能是最小值 or 羊腿已经浪费 */ return; } if (idx >= 2) // 合并 { int temp = stk[idx]; stk[--idx] += temp; dfs(step+1); stk[idx] -= temp; stk[++idx] = temp; } if (idx >= 1) // 复制 { stk[idx + 1] = stk[idx]; idx++; sum += stk[idx]; dfs(step + 1); sum -= stk[idx]; idx--; } // 生成 stk[++idx] = 1; sum++; dfs(step + 1); sum--; idx--; } void init() { for (int i = 1;i <= 100; i++) { mn = 1e9+7; n=i; idx=0; dfs(0); ans[i]=mn; } } int main() { init(); cin >> t; while (t--) { scanf("%d", &n); printf("%d\n", ans[n]); } return 0; }
题目描述
众所周知,唐克老师家里存着非常多的羊腿,一共有 m 只,依次编号为 1~ m,每只羊腿都有自己的大小 bi
当然,作为强迫症的唐克老师已经将这 m 只羊腿从小到大排好了。
现在唐克老师准备请群里一共 n 个小伙伴吃羊腿。
为了不浪费粮食,唐克老师统计了每个小伙伴的食量 ai,表示第 i 个小伙伴最多只能吃下编号为 ai 的羊腿
当然,为了公平,每个小伙伴只能分到一个羊腿。
如果某个小伙伴 x 没有办法分到适合他吃的羊腿,那么唐克老师会为他准备好质量为 bax 的牛肉来补偿他
现在唐克老师想知道,他最少需要准备多少质量的牛肉?
当然,作为强迫症的唐克老师已经将这 m 只羊腿从小到大排好了。
现在唐克老师准备请群里一共 n 个小伙伴吃羊腿。
为了不浪费粮食,唐克老师统计了每个小伙伴的食量 ai,表示第 i 个小伙伴最多只能吃下编号为 ai 的羊腿
当然,为了公平,每个小伙伴只能分到一个羊腿。
如果某个小伙伴 x 没有办法分到适合他吃的羊腿,那么唐克老师会为他准备好质量为 bax 的牛肉来补偿他
现在唐克老师想知道,他最少需要准备多少质量的牛肉?
输入
输入第一行包含两个正整数 n,m,表示有 n 个小伙伴和 m 个羊腿
第二行包含 n 个整数 ai,分别表示每个小伙伴的食量
第三行包含 m 个整数 bi,分别表示每个羊腿的大小
对于 20% 的数据: n,m≤10
对于 60% 的数据: n,m,ai≤10000
对于 100% 的数据:n,m≤100000, 1≤bi≤109,1≤ai≤m
第二行包含 n 个整数 ai,分别表示每个小伙伴的食量
第三行包含 m 个整数 bi,分别表示每个羊腿的大小
对于 20% 的数据: n,m≤10
对于 60% 的数据: n,m,ai≤10000
对于 100% 的数据:n,m≤100000, 1≤bi≤109,1≤ai≤m
输出
输出唐克老师最少需要准备的牛肉质量
样例输入 Copy
5 4
2 3 4 3 2
3 9 20 100
样例输出 Copy
9
#include <bits/stdc++.h> using namespace std; const int N = 1e5 + 5; using ll = long long; ll a[N], b[N], res; int main() { int n, m; cin >> n >> m; for (int i = 1; i <= n; i++) scanf("%lld", &a[i]); for (int i = 1; i <= m; i++) scanf("%lld", &b[i]); sort(a + 1, a + n + 1); ll lftidx = a[n]; for (int i = n; i >= 1; i--) { if (lftidx > 0) // 还有羊腿 { if (a[i] >= lftidx) // 还能吃 { lftidx--; } else // 吃不下了 { lftidx = a[i]; // 跳到能吃得下的地方 lftidx--; } } else // 没有羊腿了 { res += b[a[i]]; // 补偿牛腿数 } } cout << res << endl; return 0; }
题目描述
众所周知,唐克很喜欢玩游戏,这天他玩的游戏中新出了一个强(ke)化(jin)系统,允许玩家在一件装备上镶嵌强化石
而常规的概率强化已经无法吸引玩家了,所以新推出的这个强化系统的强化方式是这样的
每件装备拥有一个独立的强化界面,这个强化界面可以看作一个 n * m 的矩阵,每个点都可以镶嵌一颗强化石
在镶嵌了强化石后,装备的强化系数就是强化石构成的等腰三角形个数
这里的等腰三角形是指(镶嵌界面中 `.` 表示为空, `*` 表示镶嵌了强化石)
大小为 1 的三角形
```
*
```
大小为 2 的三角形
```
.*.
***
```
大小为 3 的三角形
```
..*..
.***.
*****
```
依次类推...
比如一件装备拥有一个 3 * 5 的强化界面
```
..*..
.****
*****
```
上述装备镶嵌了 10 颗强化石,获得的强化系数是 15
现在唐克已经给自己的装备镶嵌好了强化石,他想知道这件装备的强化系数是几?
而常规的概率强化已经无法吸引玩家了,所以新推出的这个强化系统的强化方式是这样的
每件装备拥有一个独立的强化界面,这个强化界面可以看作一个 n * m 的矩阵,每个点都可以镶嵌一颗强化石
在镶嵌了强化石后,装备的强化系数就是强化石构成的等腰三角形个数
这里的等腰三角形是指(镶嵌界面中 `.` 表示为空, `*` 表示镶嵌了强化石)
大小为 1 的三角形
```
*
```
大小为 2 的三角形
```
.*.
***
```
大小为 3 的三角形
```
..*..
.***.
*****
```
依次类推...
比如一件装备拥有一个 3 * 5 的强化界面
```
..*..
.****
*****
```
上述装备镶嵌了 10 颗强化石,获得的强化系数是 15
现在唐克已经给自己的装备镶嵌好了强化石,他想知道这件装备的强化系数是几?
输入
输入第一行包含两个正整数 n,m 表示这件装备的强化界面
接下来 n 行,每行一个长度为 m 的字符串,仅包含 `.` 和 `*`,其中 `.` 表示为空,`*` 表示这个格子镶嵌了强化石
接下来 n 行,每行一个长度为 m 的字符串,仅包含 `.` 和 `*`,其中 `.` 表示为空,`*` 表示这个格子镶嵌了强化石
输出
输出一个整数表示强化系数
样例输入 Copy
3 5
..*..
.****
*****
样例输出 Copy
15
提示
对于 30% 的数据: n,m ≤ 5
对于 60% 的数据: n,m ≤ 500
对于 100% 的数据:n,m ≤ 1000
对于 60% 的数据: n,m ≤ 500
对于 100% 的数据:n,m ≤ 1000
#include <bits/stdc++.h> using namespace std; int main() { int n, m; cin >> n >> m; vector<vector<int>> dp(n, vector<int>(m, 0)); vector<string> matrix(n); for (int i = 0; i < n; ++i) { cin >> matrix[i]; } for (int i = n - 1; i >= 0; --i) { for (int j = 0; j < m; ++j) { if (matrix[i][j] == '*') { dp[i][j] = 1; if (i < n - 1 && j > 0 && j < m - 1) { dp[i][j] += min({dp[i + 1][j - 1], dp[i + 1][j], dp[i + 1][j + 1]}); } } } } int ans = 0; for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { ans += dp[i][j]; } } cout << ans << '\n'; return 0; }
题目描述
唐克老师有一个长度为 n 的数组,但是这个数组发生了一些奇妙的变化——每一秒这个数组都在不断的收缩!
每一秒,相邻的两个数字会合并成一个,产生一个新的数组,一直搜索到数组只剩下两个数字
每一次的合并,就是将两个数字相加
例如有一个长度为 5 的数组 [1,2,3,4,5]
第一秒:会合并 (1,2),(3,4),因为没有第六个数字,所以 5 不变,即变成新数组 [3,7,5]
第二秒:会合并 (3,7),因为没有第四个数字,所以 5 不变,即变成新数组 [10,5]
此时,数组收缩到只有两个数字,结束变化
现在唐克老师想知道,这个数组最后两个数字的平方和会是多少?
每一秒,相邻的两个数字会合并成一个,产生一个新的数组,一直搜索到数组只剩下两个数字
每一次的合并,就是将两个数字相加
例如有一个长度为 5 的数组 [1,2,3,4,5]
第一秒:会合并 (1,2),(3,4),因为没有第六个数字,所以 5 不变,即变成新数组 [3,7,5]
第二秒:会合并 (3,7),因为没有第四个数字,所以 5 不变,即变成新数组 [10,5]
此时,数组收缩到只有两个数字,结束变化
现在唐克老师想知道,这个数组最后两个数字的平方和会是多少?
输入
第一行给出两个正整数 n,k,n 表示数组长度,k 表示输入数据组数
接下来 k 行,每行包含两个整数 x,y 表示数组接下去有 x 个数字 y,具体请看样例解释
接下来 k 行,每行包含两个整数 x,y 表示数组接下去有 x 个数字 y,具体请看样例解释
输出
输出最后两个数字的平方和,由于答案可能很大,请对 109 + 7 取模
样例输入 Copy
7 2
3 1
4 2
样例输出 Copy
61
提示
输入给出了 3 个 1 和 4 个 2,即数组为 [1,1,1,2,2,2,2],第一秒变为 [2,3,4,2],第二秒变为 [5,6],答案即为 52+62=61
对于 30% 的数据,满足 1 ≤ k ≤ n ≤ 103
对于 60% 的数据,满足 1 ≤ n ≤ 105
对于 80% 的数据,满足 1 ≤ n ≤ 1010
对于 100% 的数据,满足 1 ≤ n < 1018, 1 ≤ k ≤ 105, 1 ≤ x ≤ 106, 1 ≤ y ≤ 109。
特别的保证:对于所有数据满足Σx = n
对于 30% 的数据,满足 1 ≤ k ≤ n ≤ 103
对于 60% 的数据,满足 1 ≤ n ≤ 105
对于 80% 的数据,满足 1 ≤ n ≤ 1010
对于 100% 的数据,满足 1 ≤ n < 1018, 1 ≤ k ≤ 105, 1 ≤ x ≤ 106, 1 ≤ y ≤ 109。
特别的保证:对于所有数据满足Σx = n
#include <bits/stdc++.h> using namespace std; using ll = long long; using pll = pair<ll, ll>; const int mod = 1e9 + 7; ll n, k, ok; vector<pll> data, ans; vector<pll> process(vector<pll> data) { vector<pll> temp; // 临时数组 ll len = data.size(); // 数据中不同数的个数 ll last_x = 0, last_y; // 临时变量, 上一个x, 上一个y ok = 0; // 用来做标记的, 表示还剩【几个数】 for (int i = 0; i < len; i++) { if (last_x != 0) { // x有残留,上一个x是奇数,会剩下。 data[i].first--; temp.emplace_back(make_pair(1, (last_y + data[i].second) % mod)); ok++; last_x = last_y = 0; } ll x = data[i].first, y = data[i].second; if (x & 1) { // 奇数的特殊情况处理。 last_x = 1; x--; last_y = y; } if (x > 0) { // 合并之后放回去。 temp.emplace_back(make_pair(x / 2, y % mod * 2)); ok += x / 2; } } if (last_x != 0) { temp.emplace_back(make_pair(1, last_y)); ok++; } if (ok > 2) { // 还剩不止两个数,递归继续处理 return process(temp); } else { // 可以了,返回 return temp; } } int main() { cin >> n >> k; for (int i = 1; i <= k; i++) { ll a, b; scanf("%lld%lld", &a, &b); data.emplace_back(make_pair(a, b)); } ans = process(data); if (ans.size() == 1) { // 此时同样的数只剩一种 ll x = ans[0].second; cout << ((x % mod) * (x % mod) + (x % mod) * (x % mod)) % mod; } else { // 还有两类数 ll x = ans[0].second, y = ans[1].second; cout << ((x % mod) * (x % mod) + (y % mod) * (y % mod)) % mod; } return 0; }
浙公网安备 33010602011771号