2023JSCPC(江苏省赛)vp&补题记录
摘要
5题654罚时,一开始做的挺快的,一个半小时就四题了,然后被求数学期望的银题狠狠痛击了,另一道调了两个小时wa了9发才过掉。最后一小时微距,提前下班了。
省赛在即,加油加油。
赛时部分
I - Elevator
数学
直接输出 \(n-m+1\) 即可。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define pii pair<int, int>
#define pll pair<ll, ll>
#define endl '\n'
#define Y cout << "Yes\n"
#define N cout << "No\n"
#define fi first
#define se second
const int MOD = 1e9+7, inf = 0x3f3f3f3f;
void solve() {
ll n, m;
cin >> n >> m;
cout << n-m+1 << endl;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while(t--) solve();
return 0;
}
J - Similarity (Easy Version)
枚举
注意到数据量很小,直接枚举求出每两个字符串的相似值同时维护最大值即可。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define pii pair<int, int>
#define pll pair<ll, ll>
#define endl '\n'
#define Y cout << "Yes\n"
#define N cout << "No\n"
#define fi first
#define se second
const int MOD = 1e9+7, inf = 0x3f3f3f3f;
int get_same(string a, string b) {
int ans = 0;
for(int i = 0; i < a.size(); i ++ ) {
char c = a[i];
for(int j = 0; j < b.size(); j ++ ) {
if(b[j] != c) continue;
int i_ = i+1, j_ = j+1;
int sum = 1;
while(a[i_] == b[j_] && i_ < a.size() && j_ < b.size()) {
sum++;
i_++, j_++;
}
ans = max(ans, sum);
}
}
return ans;
}
void solve() {
int n;
cin >> n;
vector<string> alls(n);
for(int i = 0; i < n; i ++ ) cin >> alls[i];
int ans = 0;
for(int i = 0; i < n; i ++ ) {
for(int j = i+1; j < n; j ++ ) {
ans = max(ans, get_same(alls[i], alls[j]));
}
}
cout << ans << endl;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while(t--) solve();
return 0;
}
H - Neil's Machine
模拟
如果单纯根据题目进行模拟,在更新字符串的部分容易超时,需要考虑如何在模拟的过程中进行优化。
我们注意到每次操作都是对字符串的一整个后缀进行操作,也就是说当我们枚举到某一个不相同的字母时,以这个字母开头的字符串后缀在此之前变化的数值是相等的,因此我们可以维护一个 \(sum\) 来表示枚举到当前字符时,后面所有的字符的变化量。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define pii pair<int, int>
#define pll pair<ll, ll>
#define endl '\n'
#define Y cout << "Yes\n"
#define N cout << "No\n"
#define fi first
#define se second
const int MOD = 1e9+7, inf = 0x3f3f3f3f;
void solve() {
int n;
cin >> n;
string a, b;
cin >> a >> b;
int ans = 0;
int sum = 0;
for(int i = 0, j = 0; i < n; i ++, j ++ ) {
int A = a[i]-'a', B = b[j]-'a';
if(A == (B+sum)%26) continue;
sum += (A > (B+sum)%26 ? A-(B+sum)%26 : (A+26)-(B+sum)%26);
ans++;
}
cout << ans << endl;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int t = 1;
//cin >> t;
while(t--) solve();
return 0;
}
A - Today's Word
模拟
观察字符串变化方式,不难得出,当字符串的长度大于等于 \(2 \ast m\) 时,长度为 \(m\) 的后缀将不再改变。因此我们只需要维护从 \(S_0\) 到长度大于等于 \(2*m\) 的字符串的模拟次数 \(t\),然后求出 \((10^{100}-t)\%26\) 作为偏移量加到长度为 \(m\) 的后缀上即为答案。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define pii pair<int, int>
#define pll pair<ll, ll>
#define endl '\n'
#define Y cout << "Yes\n"
#define N cout << "No\n"
#define fi first
#define se second
const int MOD = 1e9+7, inf = 0x3f3f3f3f;
void solve() {
int n, m;
cin >> n >> m;
string s;
cin >> s;
ll i = 1;
int cnt = 0;
for(i = 1; s.size() <= 2*m; i ++ ) {
int len = s.size()/2;
string temp = s.substr(0, len);
temp += s;
for(int j = len; j < s.size(); j ++ ) {
s[j]++;
if(s[j] > 'z') s[j] = 'a';
}
temp += s.substr(len, len);
s = temp;
}
string temp = s.substr(s.size()-m, m);
int t;
int sum = 1;
for(int num = 1; num <= 100; num++) {
sum = (sum*10)%26;
}
while(sum < i) sum += 26;
t = (sum-i)%26;
for(int j = 0; j < temp.size(); j ++ ) {
temp[j] = (temp[j]-'a'+t+1)%26+'a';
}
cout << temp << endl;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int t = 1;
//cin >> t;
while(t--) solve();
return 0;
}
K - Similarity (Hard Version)
思维,构造
先考虑特殊情况,当 \(m=0\) 时需要让所有的字符串都没有重复字符,不难想到只要让第 \(i\) 个字符串全由 \('a'+i-1\) 组成即可。而我们知道,小写字母只有\(26\)个,也就是说当 \(m=0\) 且 \(k > 26\) 时无解。
同时,不难看出,当 \(m>=k\) 时同样无解。
接着对于一般情况,我们可以先构造一个长度为 \(k\),并且全为 \(a\) 的字符串。对于第二个字符串我们可以先让前 \(m\) 个字母为 \(a\),其余字母为 \(b\) 。
而对于后面的字符串,我们可以考虑以 acacac......,bdbdbd......的形式构造,这样构造出来的字符串相似度最大为1(注意要避开ab组合).
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define pii pair<int, int>
#define pll pair<ll, ll>
#define endl '\n'
#define Y cout << "Yes\n"
#define N cout << "No\n"
#define fi first
#define se second
const int MOD = 1e9+7, inf = 0x3f3f3f3f;
void solve() {
int n, m, k;
cin >> n >> m >> k;
if(m == 0) {
if(n <= 26) {
Y;
for(int i = 0; i < n; i ++ ) {
for(int j = 1; j <= k; j ++ ) {
cout << (char)('a'+i);
}
cout << endl;
}
} else {
N;
}
return;
}
if(m >= k) {
N;
return;
}
Y;
vector<string> ans;
for(int i = 0; i < 25; i ++ ) {
for(int j = i+1; j < 25; j ++ ) {
string temp;
temp.push_back('a'+i);
temp.push_back('a'+j);
ans.push_back(temp);
if(ans.size() == n) goto nx;
}
}
nx: ;
for(int i = 0; i < k; i ++ ) cout << 'a';
cout << endl;
for(int i = 0; i < m; i ++ ) cout << 'a';
for(int i = 0; i < k-m; i ++ ) cout << 'b';
cout << endl;
for(int i = 2; i < n; i ++ ) {
string temp;
for(int t = 1; t <= k/2; t ++ ) {
temp += ans[i];
}
if(k%2) temp += ans[i][0];
cout << temp << endl;
}
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int t = 1;
//cin >> t;
while(t--) solve();
return 0;
}
补题部分
F - Timaeus
数学,dp
期望是试验中每次可能结果的概率乘以其结果的总和。
我们考虑用 \(dp_i\) 来表示剩下 \(i\) 个材料时的最大期望数量。
因为每次只能选择一种buff:
- \(P\%\) 的概率合成双倍物品;
- \(Q\%\) 的概率返还一个物品;
所以对于每一个 \(dp_i\) 可以由前面的某种情况选择其中一个buff转移而来。
得到方程:
此外,当 \(B=1\) 时,只使用第二种buff是最优的,即有 \(Q\) 概率不消耗材料。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define pii pair<int, int>
#define pll pair<ll, ll>
#define endl '\n'
#define Y cout << "YES\n"
#define N cout << "NO\n"
#define fi first
#define se second
const int MOD = 1e9+7, inf = 0x3f3f3f3f;
void solve() {
int a, b;
double p, q;
cin >> a >> b >> p >> q;
p /= 100, q /= 100;
vector<double> f(a+1, 0);
for(int i = b; i <= a; i ++ ) {
f[i] = max(p*(f[i-b]+2)+(1-p)*(f[i-b]+1), q*(f[i-b+1]+1)+(1-q)*(f[i-b]+1));
}
double ans;
if(b == 1) ans = max(a*1.0/(1-q), f[a]);
else ans = f[a];
cout << fixed << setprecision(12) << ans << endl;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int t = 1;
//cin >> t;
while(t--) solve();
return 0;
}

浙公网安备 33010602011771号