C - Error Correction
tag:字符串,模拟
题解:
跟着题意模拟一遍即可
// 加油昂!!!
// Problem: C - Error Correction
// Contest: AtCoder - Japan Registry Services (JPRS) Programming Contest 2023 (AtCoder Beginner Contest 324)
// URL: https://atcoder.jp/contests/abc324/tasks/abc324_c
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef double db;
const int N = 5e5 + 5, M = 1e9 + 7, mod = 998244353;
#define YES {cout<<"YES"<<endl;return ;}
#define NO {cout<<"NO"<<endl;return ;}
int n, m, k;
string s[N];
string T;
bool check(string ss)
{
if (ss == T) return true;
if (ss.size() == T.size())
{
for (int i = 0; i < ss.size(); i++)
{
if (ss[i] != T[i])
{
ss[i] = T[i];
break;
}
}
}
else if (ss.size() == T.size() + 1)
{
for (int i = 0; i < ss.size(); i++)
{
if (ss[i] != T[i] || i == T.size())
{
ss.erase(ss.begin() + i);
break;
}
}
}
else if (ss.size() + 1 == T.size())
{
for (int i = 0; i < T.size(); i++)
{
if (ss[i] != T[i] || i == ss.size())
{
ss.insert(ss.begin() + i, T[i]);
break;
}
}
}
if (ss == T) return true;
return false;
}
void solve()
{
cin >> n;
cin >> T;
vector<int> ans;
for (int i = 1; i <= n; i++)
{
cin >> s[i];
if (check(s[i])) ans.push_back(i);
}
cout << ans.size() << "\n";
for (auto x : ans) cout << x << " ";
cout << "\n";
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
//cin >> t;
while (t--)
solve();
return 0;
}
D - Square Permutation
tag:模拟
题解:
从范围可以看出,这题不能遍历一遍所有数字,可以发现答案只可能是sqrt(1e13),那我们就遍历到x * x <= 1e13,每次得到了一串数字之后,把他转换为字符串,如果与给定数字位数不用,就添加0,然后排序比较大小即可判断是否相等。(我犯了一个低级错误,忘记把0 * 0 == 0算上了)
// 加油昂!!!
// Problem: D - Square Permutation
// Contest: AtCoder - Japan Registry Services (JPRS) Programming Contest 2023 (AtCoder Beginner Contest 324)
// URL: https://atcoder.jp/contests/abc324/tasks/abc324_d
// Memory Limit: 1024 MB
// Time Limit: 4000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef double db;
const int N = 4e6 + 5, M = 1e9 + 7, mod = 998244353;
#define YES {cout<<"YES"<<endl;return ;}
#define NO {cout<<"NO"<<endl;return ;}
int n, m, k;
string s;
bool check(string t)
{
sort(t.begin(),t.end());
if (s == t) return true;
return false;
}
void solve()
{
cin >> n;
cin >> s;
sort(s.begin(),s.end());
int ans = 0;
for (int i = 0; i <= 1e13 / i; i++)
{
int x = i * i;
string res = to_string(x);
if (res.size() > s.size()) break;
for (int j = s.size() - res.size(); j > 0; j--)
{
res = "0" + res;
}
if (check(res)) ans++;
}
cout << ans << "\n";
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
//cin >> t;
while (t--)
solve();
return 0;
}
E - Joint Two Strings
tag:前缀和,模拟
题解:
和我一开始思路一样,就是我看错了一个条件从而否决了自己的想法,我以为他不能使用自己。因为自己可以和n个字符串中的任意一个组合,且是子序列即可。那我们就记录每个字符串中分别从前往后和从后往前能有多少个相同的,比如给定字符串为:abc,现在的字符串是bac,那么这个字符串从前面往后面就是一个相同的,即:a,而从后面往前面就是两个相同的,即:bc。先对从后往前求出的长度求出一个前缀和,然后我们将i从1循环到给定字符串的长度,分别求出每一个从前往后能匹配i长度的字符串,能和多少个大于等于n-i的字符串相匹配,然后相乘求和即可。
// 加油昂!!!
// Problem: E - Joint Two Strings
// Contest: AtCoder - Japan Registry Services (JPRS) Programming Contest 2023 (AtCoder Beginner Contest 324)
// URL: https://atcoder.jp/contests/abc324/tasks/abc324_e
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef double db;
const int N = 5e5 + 5, M = 1e9 + 7, mod = 998244353;
#define YES {cout<<"YES"<<endl;return ;}
#define NO {cout<<"NO"<<endl;return ;}
int n, m, k;
int h[N], q[N];
int sh[N];
void solve()
{
cin >> n;
string t;
cin >> t;
int ans = 0;
for (int i = 1; i <= n; i++)
{
string s;
cin >> s;
int res1 = 0, last = 0;
for (int j = 0; j < s.size() && last < t.size(); j++)
{
if (s[j] == t[last])
{
res1++;
last++;
}
}
q[res1]++;
int res2 = 0;
last = t.size() - 1;
for (int j = s.size() - 1; j >= 0 && last >= 0; j--)
{
if (s[j] == t[last])
{
res2++;
last--;
}
}
h[res2]++;
}
for (int i = 0; i <= t.size(); i++)
{
if (i == 0)
{
sh[i] = h[i];
}
else
{
sh[i] = sh[i - 1] + h[i];
}
}
for (int i = 0; i <= t.size(); i++)
{
if (i == t.size()) ans += q[i] * sh[i];
else ans += q[i] * (sh[t.size()] - sh[t.size() - i - 1]);
}
cout << ans << "\n";
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
//cin >> t;
while (t--)
solve();
return 0;
}
F - Beautiful Path
tag:二分,DP
题解:
我们用sumb表示路径上所有b的和,sumc表示路径上所有c的和,因为要求sumb/sumc的最大值,即可转化为求一个最大的x,满足sumb/sumc >= x,因此sumb - sumc * x >= 0,在二分判断的时候,判断的依据是:DP出的路径大于等于0为真,否则为假,因为这题的特殊性,所以我们可以直接用一个结构体进行排序,就能保证每一个小的点在更新别人之前自己已经被更新彻底。
// 加油昂!!!
// Problem: F - Beautiful Path
// Contest: AtCoder - Japan Registry Services (JPRS) Programming Contest 2023 (AtCoder Beginner Contest 324)
// URL: https://atcoder.jp/contests/abc324/tasks/abc324_f
// Memory Limit: 1024 MB
// Time Limit: 5000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef double db;
const int N = 2e5 + 5, M = 1e9 + 7, mod = 998244353;
const double eps = 1e-11;
#define YES {cout<<"YES"<<endl;return ;}
#define NO {cout<<"NO"<<endl;return ;}
int n, m, k;
struct node{
int u, v, b, c;
}p[N];
db dp[N];
bool cmp(node a, node b)
{
return a.u < b.u;
}
bool check(db mid)
{
for (int i = 1; i <= n; i++)
{
dp[i] = -INT_MAX;
}
dp[1] = 0;
for (int i = 1; i <= m; i++)
{
int u = p[i].u, v = p[i].v, b = p[i].b, c = p[i].c;
dp[v] = max(dp[v], dp[u] + b * 1.0 - c * mid);
}
return dp[n] > 0;
}
void solve()
{
cin >> n >> m;
for (int i = 1; i <= m; i++)
{
cin >> p[i].u >> p[i].v >> p[i].b >> p[i].c;
}
sort(p + 1, p + m + 1, cmp);
db l = eps, r = 1e4;
while (r - l > eps)
{
db mid = (l + r) / 2;
if (check(mid)) l = mid;
else r = mid;
}
cout << fixed << setprecision(10) << r << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
//cin >> t;
while (t--)
solve();
return 0;
}