A - Find Takahashi
题意:找到给定的数组中最大元素的下标
思路:水题(没有什么参考价值)
时间复杂度:O(n)
代码:
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
int maxx = 0;
int ans;
for (int i = 1; i <= n; i ++ ) {
int x;
cin >> x;
if(x > maxx) {
maxx = x;
ans = i;
}
}
cout << ans << endl;
return 0;
}
B - ABC-DEF
题意:对于给定的A, B, C, D, E, F六个数,求出:(A×B×C)−(D×E×F) % 998244353
思路:对其应用取模规则
乘法取余: A * B % mod = ((A % mod) * (B % mod)) % mod
加法取余:(A + B) % mod = ((A % mod) + (B % mod)) % mod
减法取余:(A - B) % mod = (A % mod - B % mod + mod) % mod
整除取余:(A / B) % mod = (A % mod * B ^ (mod - 2) * mod) % mod
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 998244353;
LL a, b, c, d, e, f;
int main() {
cin >> a >> b >> c >> d >> e >> f;
LL temp = (((a % mod) * (b % mod) % mod) * (c % mod) % mod) % mod;
LL temp1 = (((d % mod) * (e % mod) % mod) * (f % mod) % mod) % mod;
LL ans = (temp % mod - temp1 % mod + mod) % mod;
cout << ans << endl;
return 0;
}
C - Counting Squares
题意:在一个9 * 9的矩阵中,有多少个四个点都是‘#’组成的正方形
思路:模拟,通过枚举正方形的两个相邻的顶点,计算出另外的两个顶点,由于是在9 * 9的方格中,所以时间复杂度是满足的
时间复杂度:O(81 * 81)
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 100;
char g[N][N];
bool solve(int x, int y) {
if(x >= 1 && x <= 9 && y >=1 && y <= 9 && g[x][y] == '#') {
return true;
}
return false;
}
int main() {
for (int i = 1; i <= 9; i ++ ) {
for (int j = 1; j <= 9; j ++ ) {
cin >> g[i][j];
}
}
int ans = 0;
for (int x1 = 1; x1 <= 9; x1 ++ ) {
for (int y1 = 1; y1 <= 9; y1 ++ ) {
for (int x2 = 1; x2 <= 9; x2 ++ ) {
for (int y2 = 1; y2 <= 9; y2 ++ ) {
if(x1 == x2 && y1 == y2) continue;
if(g[x1][y1] == '.' || g[x2][y2] == '.') continue;
int x3 = x2 - (y2 - y1);
int y3 = y2 - (x1 - x2);
int x4 = x1 - (y2 - y1);
int y4 = y1 - (x1 - x2);
if(solve(x3, y3) && solve(x4, y4)) {
ans ++ ;
}
}
}
}
}
cout << ans / 4 << endl;
return 0;
}
D - Yet Another Recursive Function
题意:定义函数f(0) = 1, 并且f(k) = f(k / 2) + f(k / 3) 此时的除法都是下取整,给定n,计算f(n)
思路:运行时间是两秒,n的范围是在long long中,,若是仅使用递归处理会发现运行超时,dp的话,无法用数组表示到1e18的范围,所以可以使用记忆化搜索,用unordered_map<LL, LL> mp记录已经计算过的值,使用时,直接在O(1)的时间内查找
时间复杂度:不太会看
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
unordered_map<LL, LL> mp;
LL f(LL n) {
if(mp.count(n)) return mp[n];
if(!n) return 1;
return mp[n] = f(n / 2) + f(n / 3);
}
int main() {
LL n;
cin >> n;
cout << f(n) << endl;
return 0;
}
E - Sugoroku 4
题意:有n + 1个区域,分别是从0 - n,Takahashi想从0出发,最后到达n区域,每一次走多少通过转轮盘决定,轮盘的值是1 - M,当目前所在的区域i,与转到的路程j,有i + j > n的话,需要从n向0区域走(i + j - n)个距离
问:Takahashi在最多K次移动内到达n区域的总概率(% 998244353)
思路:dp解决,
集合:dp[i][j]表示在i次移动之内,正好到达j区域的总概率
属性:count(总和)
状态转移方程:
假设现在是i次移动内,达到j区域的总概率
对于本次之后的移动,有M种可能,可以分成两类:
1、当i + k <= M 的时候,dp[i + 1][j + k] += dp[i][j] / M (%998244353)
2、当i + k > M 的时候,dp[i + 1][2 * n - j - k] += dp[i][j] / M (%998244353)
在通过取余转换式,将两个式子转换,注意:
(A / B) % mod = (A % mod * B ^ (mod - 2) % mod) % mod
时间复杂度:O((N - 1) * M * K)
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int mod = 998244353;
const int N = 1100;
LL f[N][N];
//快速幂
LL qpow(LL a, LL b) {
LL ans = 1;
while (b) {
if(b & 1) ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans;
}
int main() {
int n, m, cnt;
cin >> n >> m >> cnt;
LL M = qpow(m, mod - 2);
f[0][0] = 1;
for (int i = 0; i <= cnt; i ++ ) {
for (int j = 0; j < n; j ++ ) {
for (int k = 1; k <= m; k ++ ) {
if(j + k <= n) {
f[i + 1][j + k] = (f[i + 1][j + k] + f[i][j] * M) % mod;
}
else {
f[i + 1][2 * n - j - k] = (f[i + 1][2 * n - j - k] + f[i][j] * M) % mod;
}
}
}
}
LL ans = 0;
for (int i = 0; i <= cnt; i ++ ) {
ans = (ans + f[i][n]) % mod;
}
cout << ans << endl;
return 0;
}
F - Erase Subarrays
题意:给定一个数组,你可以在数组中删除连续的区间,问:使得数组剩余的总和为x (x=1,2,…,M)分别需要删除多少个连续的区间
思路:动态规划dp,
集合:假设dp[i][j]表示考虑前i个数,当前保留数的总和是j的最小操作数
属性:Min
状态转移:我们同样来考虑最后一个数a[i]的取舍
1、当保留a[i]的时候,f[i][j] = min(f[i][j], f[i - 1][j - a[i]])
2、当不保留a[i](即进行删除操作)的时候, 我们需要枚举删除的连续一段是多少
dp[i][j] = min(dp[i][j], dp[k - 1][j] + 1) 其中 (1 <= k <= i)
这样的话时间复杂度是O(n ^ 3),数据范围是3000,3000 ^ 3 = 3 e 10,计算机一秒内最多计算1e7- 1e8左右所以会超时,这是我们可以使用一个数组pre[i][j] 来记录f[0][j], f[1][j], f[2][k],...,f[i][j]的最小值
此时的时间复杂度就是:O(n ^ 2),一秒内可以完成
代码:
#include <bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
const int N = 3100;
int f[N][N];
int pre[N][N];
int a[N];
int main() {
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i ++ ) cin >> a[i];
memset(f, inf, sizeof f);
memset(pre, inf, sizeof pre);
f[0][0] = 0;
pre[0][0] = 0;
for (int i = 1; i <= n; i ++ ) {
for (int j = 0; j <= m; j ++ ) {
if(j - a[i] >= 0) {
f[i][j] = min(f[i][j], f[i - 1][j - a[i]]);
}
f[i][j] = min(f[i][j], pre[j][i - 1] + 1);
pre[j][i] = min(f[i][j], pre[j][i - 1]);
}
}
for (int i = 1; i <= m; i ++ ) {
if(f[n][i] == inf) f[n][i] = -1;
printf("%d\n", f[n][i]);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架