前言:
- 代码参考于Atcoder官方题解
A - Adjacent Product
思路:
- 跳过
以下是代码部分
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e2 + 10;
int a[N], b[N];
void solve()
{
int n;
cin >> n;
for(int i = 1; i <= n; i ++)
cin >> a[i];
for(int i = 2; i <= n; i ++)
{
cout << a[i - 1] * a[i] << " \n"[i == n];
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
//cin >> t;
while(t --)
solve();
return 0;
}
B - Piano
思路:
- 暴力枚举每一种状态
以下是代码部分
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e2 + 10;
void solve()
{
string s = "wbwbwwbwbwbw";
int w, b;
cin >> w >> b;
int sum = w + b;
//总共12种排列方法
for(int i = 0; i < 12; i ++)
{
int tempw = 0, tempb = 0;
//暴力枚举
for(int j = i; j < sum + i; j ++)
{
if(s[j % 12] == 'w') tempw ++;
else tempb ++;
}
if(tempw == w && tempb == b)
{
cout << "Yes\n";
return ;
}
}
cout << "No\n";
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
//cin >> t;
while(t --)
solve();
return 0;
}
C - Σ
思路:
- 1 − k 1-k 1−k的和用等差数列求和公式 减去 在a中出现过的数即可
以下是代码部分
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e2 + 10;
set<int> a;
void solve()
{
int n, k;
cin >> n >> k;
//
for(int i = 1; i <= n; i ++)
{
int x; cin >> x;
//存入到set集合中
a.insert(x);
}
//等差数列求和
ll sum = (1 + (ll)k) * (ll)k / 2;
for(auto it : a)
{
//如果在数组a[]中,就减去
if(it > k) break;
sum -= it;
}
cout << sum << '\n';
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
//cin >> t;
while(t --)
solve();
return 0;
}
D - Gomamayo Sequence
思路1.前缀和:
f0
代表010101010101……
的字符串f1
代表101010101010……
的字符串g0
代表……101010101010
的字符串g0
代表……010101010101
的字符串- 后面只需要遍历,找到拼接后的最小值即可
以下是代码部分, 代码参考来源——atcoder官方题解
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
const int N = 1e6 + 10;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
string s; cin >> s;
vector<i64> c(n);
for(int i = 0; i < n; i ++) cin >> c[i];
vector<i64> f0(n + 1), f1(n + 1), g0(n + 1), g1(n + 1);
for(int i = 0; i < n; i ++)
{
f0[i + 1] = f0[i];
f1[i + 1] = f1[i];
if(i&1)
s[i] == '0' ? f0[i + 1] += c[i] : f1[i + 1] += c[i];
else
s[i] == '0' ? f1[i + 1] += c[i] : f0[i + 1] += c[i];
}
for(int i = n - 1; i >= 0; i --)
{
g0[i] = g0[i + 1];
g1[i] = g1[i + 1];
if(i&1)
s[i] == '0' ? g1[i] += c[i] : g0[i] += c[i];
else
s[i] == '0' ? g0[i] += c[i] : g1[i] += c[i];
}
i64 ans = 1e18;
for(int i = 1; i < n; i ++) ans = min(ans, f0[i] + g0[i]);
for(int i = 1; i < n; i ++) ans = min(ans, f1[i] + g1[i]);
cout << ans << '\n';
return 0;
}
思路2.DP:
- 定义
d
p
[
i
]
[
j
]
[
k
]
dp[i][j][k]
dp[i][j][k]
-
d p [ 1 − i 的下标 ] [ 在 1 − i 内,相邻的字符相等的对数 ] [ 第 i 个字符变为 k ] = { 最小花费 } dp[1 - i 的下标][在1 - i 内,相邻的字符相等的对数][第i个字符变为k] = \{最小花费\} dp[1−i的下标][在1−i内,相邻的字符相等的对数][第i个字符变为k]={最小花费}
-
可得状态转移方程
1.如果 S i S_i Si ='0'
- 则
dp[i][j][0] = min(dp[i - 1][j][1], dp[i - 1][j - 1][0]);
2.如果 S i S_i Si =
'1'
- 则
dp[i][j][0] = min(dp[i - 1][j - 1][0], dp[i - 1][j][1]) + C[i]
- 则
-
d p [ i ] [ j ] [ 1 ] dp[i][j][1] dp[i][j][1]的同理可得
-
以下是代码部分, 代码参考来源——atcoder官方题解
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
ll INF = 1e18;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
string s;
cin >> s;
vector<ll> c(n);
for(int i = 0; i < n; i ++) cin >> c[i];
// 三维数组的创建
// 第一维的空间 第二维 第三维
vector dp(n, vector(2, vector(2, INF)));
dp[0][0][s[0] - '0'] = 0;
dp[0][0][(s[0] - '0') ^ 1] = c[0];
for(int i = 1; i < n; i ++)
{
int r = s[i] - '0';
for(int k = 0; k < 2; k ++)
{
dp[i][0][k] = dp[i - 1][0][k ^ 1] + (r == k ? 0 : c[i]);
dp[i][1][k] = min(dp[i - 1][0][k], dp[i - 1][1][k ^ 1]) + (r == k ? 0 : c[i]);
}
}
cout << min(dp[n - 1][1][0], dp[n - 1][1][1]);
return 0;
}
E - Paint
思路:
- 网格上的颜色为最后涂到的颜色,换句话说,最后一次涂到的颜色就是该网格的颜色
- 所以应该反着思考,从后往前遍历,查询颜色的类型及数量就行了。
- 可以使用桶排的方式,来做到快速排序
以下是代码部分, 代码参考来源——atcoder官方题解
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int h, w, m;
cin >> h >> w >> m;
vector<bool> f(h), g(w);
ll hc = h, wc = w;
vector<int> t(m), a(m), x(m);
//输入
for(int i = 0; i < m; i ++)
cin >> t[i] >> a[i] >> x[i];
//使下标从0开始——做到下标统一
for(int i = 0; i < m; i ++)
a[i] --;
//颜色最大为2e5, 做桶排,并统计数量
int X = 2e5 + 10;
vector<ll> cnt(X);
//后面的颜色必然会覆盖前面的颜色,所以反着考虑
for(int i = m - 1; i >= 0; i --)
{
//若为行操作
if(t[i] == 1)
{
//如果该行没有被颜料涂过
if(!f[a[i]])
{
//行的每一次有效操作,会减少列每次有效操作的涂颜色的数量
hc --;
f[a[i]] = true;
cnt[x[i]] += wc;
}
}
//若为列操作
else
{
//如果该列没有被颜料涂过
if(!g[a[i]])
{
//列的每一次有效操作,会减少行每次有效操作的涂颜色的数量
wc --;
g[a[i]] = true;
cnt[x[i]] += hc;
}
}
}
//0的数量要加上剩下的没有被颜色涂过的地方
cnt[0] += hc * wc;
//存储,输出答案
vector<pair<ll, ll>> ans;
for(int i = 0; i < X; i ++)
if(cnt[i])
ans.emplace_back(i, cnt[i]);
cout << ans.size() << '\n';
for(auto p : ans)
cout << p.first << ' ' << p.second << '\n';
return 0;
}