Educational Codeforces Round 103 (A~E)
A. K-divisible Sum
/**
* Educational Codeforces Round 103 (Rated for Div. 2)
* c++11
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
void solve()
{
int n, k;
scanf("%d%d", &n, &k);
int ans;
if (k < n) ans = 1+(n%k!=0);
else ans = k/n+(k%n!=0);
printf("%d\n", ans);
}
int main()
{
int t = 1;
scanf("%d", &t);
while (t--) {
solve();
}
return 0;
}
B. Inflation
/**
* Educational Codeforces Round 103 (Rated for Div. 2)
* c++11
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
void solve()
{
int n, k;
scanf("%d%d", &n, &k);
vector<int> p(n);
for (auto &t : p) scanf("%d", &t);
LL sum = p[0];
LL ans = 0;
for (int i = 1; i < n; sum += p[i], ++i) {
if (sum*k >= p[i]*100LL) continue;
LL t = (p[i]*100LL+k-1)/k;
ans = max(t-sum, ans);
}
printf("%lld\n", ans);
}
int main()
{
int t = 1;
scanf("%d", &t);
while (t--) {
solve();
}
return 0;
}
C. Longest Simple Cycle(dp)
\(dp_i\) 代表以第 \(i\) 条链为右边界的 \(LSC(Longest\ Simple\ Cycle)\) 。
如:对第一个样例 \(dp_2=6,dp_3=4,dp_4=7,ans=max(6,4,7)=7\) 。
\(dp\) 可递推求得。
时间复杂度 \(O(n)\) 。
/**
* Educational Codeforces Round 103 (Rated for Div. 2)
* c++11
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
void solve()
{
int n;
scanf("%d", &n);
vector<int> c(n+1), a(n+1), b(n+1);
for (int i = 1; i <= n; ++i) scanf("%d", &c[i]);
for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
for (int i = 1; i <= n; ++i) scanf("%d", &b[i]);
vector<LL> dp(n+1);
LL ans = 0;
for (int i = 2; i <= n; ++i) {
int t = abs(a[i]-b[i])+1;
if (t == 1) {
dp[i] = c[i]+t;
}
else {
dp[i] = max(0LL+c[i]+t, dp[i-1]+c[i]-t+2);
}
// cout << '#' << dp[i];
ans = max(ans, dp[i]);
}
// cout << endl;
printf("%lld\n", ans);
}
int main()
{
int t = 1;
scanf("%d", &t);
while (t--) {
solve();
}
return 0;
}
D. Journey(dp)
根据题意,
若城市右侧道路为 \(RLRLRL\cdots\) 则可一直向右走。
若城市左侧道路为 \(\cdots RLRLRL\) 则可一直向左走。
记 \(dpL_i\) 为从 \(i\) 个城市向左走能通过的道路数, \(dpR_i\) 为从第 \(i-1\) 个城市向右走能通过的道路数。
从第 \(i\) 个城市出发能访问的城市数量为 \(dpL_{i}+dpR_{i+1}+1\) 。
时间复杂度 \(O(n)\) 。
/**
* Educational Codeforces Round 103 (Rated for Div. 2)
* c++11
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 3e5+5;
char s[N];
int dpL[N], dpR[N];
void solve()
{
int n;
scanf("%d%*c", &n);
gets(s+1);
dpL[0] = 0;
dpL[1] = (s[1] == 'L');
for (int i = 2; i <= n; ++i) {
if (s[i] != 'L') dpL[i] = 0;
else if (s[i-1] != 'R') dpL[i] = 1;
else dpL[i] = dpL[i-2]+2;
}
dpR[n+1] = 0;
dpR[n] = (s[n] == 'R');
for (int i = n-1; i >= 1; --i) {
if (s[i] != 'R') dpR[i] = 0;
else if (s[i+1] != 'L') dpR[i] = 1;
else dpR[i] = dpR[i+2]+2;
}
for (int i = 0; i <= n; ++i) {
printf("%d ", dpL[i]+dpR[i+1]+1);
}
puts("");
}
int main()
{
int t = 1;
scanf("%d", &t);
while (t--) {
solve();
}
return 0;
}
E. Pattern Matching(拓扑排序)
以模式串序号为顶点建图,若模式串 \(i\) 必须出现在模式串 \(j\) 前面,则从顶点 \(i\) 到顶点 \(j\) 建立一条有向边。
一个字符串最多可匹配 \(2^k\) 种模式, \(1\le k\le 4\) ,故可枚举与一个字符串匹配的所有模式串的下标,该字符串应最先匹配的模式串下标与其它下标之间存在有向边。
最终形成一个有向图,若有环,则不存在满足条件的序列;否则为 \(DAG\) 图,拓扑排序结果即为最终答案。
由于 \(k\) 很小,若模式串用哈希存储,则时间复杂度为 \(O(n)\) 级别。
/**
* Educational Codeforces Round 103 (Rated for Div. 2)
* c++11
* 模式串不超过 27^4 = 531441 种
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e6;
int pattern[N];
int encode(string &s)
{
int res = 0;
for (auto &c : s) {
res *= 27;
if (c == '_') res += 0;
else res += c^0x60;
}
return res;
}
void solve()
{
int n, m, k;
cin >> n >> m >> k;
vector< vector<int> > adj(n+1);
vector<int> in(n+1);
for (int i = 0; i < n; ++i) {
string p; cin >> p;
pattern[encode(p)] = i+1;
}
for (int i = 0; i < m; ++i) {
string s; int mt;
cin >> s >> mt;
bool match = 0;
for (int b = 0; b < (1<<k); ++b) {
string t = s;
{
int x = b, i = 0;
while (x) {
if (x&1) t[i] = '_';
++i;
x >>= 1;
}
}
int index = pattern[encode(t)];
match |= (index == mt);
if (index == 0 || index == mt) continue;
else adj[mt].push_back(index), ++in[index];
}
if (!match) {
cout << "NO";
return;
}
}
queue<int> Q;
vector<int> ans;
for (int i = 1; i <= n; ++i) {
if (in[i] == 0) Q.push(i);
}
while (!Q.empty()) {
int t = Q.front(); Q.pop();
ans.push_back(t);
for (int i = 0; i < adj[t].size(); ++i) {
int nxt = adj[t][i];
if (--in[nxt] == 0) Q.push(nxt);
}
}
if (ans.size() != n) cout << "NO";
else {
cout << "YES" << endl;
for (auto &i : ans) cout << i << ' ';
}
}
int main()
{
ios::sync_with_stdio(0); cin.tie(0);
int t = 1;
// scanf("%d", &t);
while (t--) {
solve();
}
return 0;
}