周赛9题解
A
按要求输出即可
void solve() {
int n;
string s;
cin >> n >> s;
cout << (n >= 3200 ? s : "red");
}
为了抢一血没好好看题wa了一发。。。
B
按要求输出,没看数据范围稍微有点写复杂了...算是小小当了一波??
void solve() {
int k, x;
cin >> k >> x;
for (int i = max(-1000000, x - k + 1); i <= min(1000000, x + k - 1); ++i) {
cout << i << ' ';
}
}
C
读完题发现个数一样就行,然后因为字符串最多到10所以直接map套string就好了,如果字符串比较长可以map套vector统计一下每个字母出现的个数,不过如果字符串长度小于26显然就更慢了。
void solve() {
int n;
cin >> n;
map mp;
ll ans = 0;
for (int i = 0; i < n; ++i) {
string s;
cin >> s;
sort(s.begin(), s.end());
mp[s]++;
}
for (auto & i : mp) {
ll tmp = i.second;
if (tmp < 2) continue;
ans += (tmp - 1) * tmp / 2;
}
cout << ans;
}
D
裸dfs,遍历一下就好了把父结点的权值加到子结点。
struct Node {
int to, ne;
} edg[N * 2];
int head[N], tot;
ll a[N];
void add(int u, int v) {
edg[++tot].to = v;
edg[tot].ne = head[u];
head[u] = tot;
}
void dfs(int u, int pa) {
for (int i = head[u]; i; i = edg[i].ne) {
int to = edg[i].to;
if (to == pa) continue;
a[to] += a[u];
dfs(to, u);
}
}
void solve() {
int n, m;
cin >> n >> m;
for (int i = 1; i < n; ++i) {
int u, v;
cin >> u >> v;
add(u, v), add(v, u);
}
for (int i = 0; i < m; ++i) {
int p, x;
cin >> p >> x;
a[p] += x;
}
dfs(1, 0);
for (int i = 1; i <= n; ++i) {
cout << a[i] << ' ';
}
}
E
挺有趣的但也不难,像是字符串中指定子序列的出现次数之类的题其实做的比较多了,所以贪心匹配比较好想,但显然需要优化,优化的话也是典中典,从后面扫一遍加快模拟就行,这种思路已经是第二次出现在周赛了,上上次的cf也的c我也是这么写的,比推公式要简单很多。
int f[N][26];
void solve() {
string s, t;
cin >> s >> t;
int sn = s.size(), tn = t.size();
s = char(123) + s;
t = char(123) + t;
vector ch(30);
for (int i = sn; ~i; --i) {
for (int j = 0; j < 26; ++j) {
f[i][j] = ch[j];
}
ch[s[i] - 'a'] = i;
}
ll cnt = 0, j = 0;
for (int i = 1; i <= tn; ++i) {
int now = t[i] - 'a';
if (!ch[now]) {
cout << -1;
return;
}
else {
if (f[j][now]) {
j = f[j][now];
}
else {
j = ch[now];
++cnt;
}
}
}
cout << cnt * sn + j;
}
插播一下上上次cf的C因为idea基本一致
Dashboard - Deltix Round, Autumn 2021 (open for everyone, rated, Div. 1 + Div. 2) - Codeforces
这场其他题我应该不会补。。因为题面真的恶心人,d死活没读懂然后别人一解释题意就秒了
ll n, e, k, a[N], f[N];
int npr[N], pr[N];
void Shai(int n) {
for(int i = 2 ;i <= n; ++i) {
if(!npr[i]) pr[++pr[0]] = i;
for(int j = 1; j <= pr[0] && i * pr[j] <= n && (npr[i * pr[j]] = pr[j]); ++j)
if(i % pr[j] == 0) break;
}
}
void solve() {
cin >> n >> e;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
f[i] = 0;
}
for (int i = n; i; --i) {
if (i + e <= n && a[i + e] == 1) f[i] += f[i + e];
if (a[i] == 1) ++f[i];
}
ll ans = 0;
for (int i = 1; i <= n; ++i) {
if (a[i] == 1) {
ll tmp = f[i];
if (i + tmp * e <= n && !npr[a[i + tmp * e]]) {
ans += f[i + tmp * e] + 1;
}
}
else if (!npr[a[i]]) {
ans += f[i];
}
}
cout << ans << nl;
}
就还是从后往前处理一下就好了,然后就可以按题意模拟算答案了,素数其实暴力判断都能过,不过我还是筛了一下
F
思考了一会儿没想出来怎么数位dp,感觉是个妙妙题就没做了,不过看题解感觉可以补待补题,这种难题不做就永远不会但是我马上应该会总结一下数位dp就放到那时候再补吧(
还是看题解提前补了,因为下次一定就不知道是那一次了(
这道题需要先把 y mod x 转化一下
发现需要 x 和 y 位数相同,最高位同时为 1
然后就把问题转化成了满足 y - x = y ^ x 的对数
对于这个显然如果 y 二进制下为 1 x 为 0 或 1,y 为 0 则 x 比为 0
然后就可以数位dp了
然后这个写法比经典数位dp感觉更妙一点
ll f[N][2][2][2], L, R, ml[N], mr[N];
ll dfs(int d, int fl, int fr, bool lead) {
if (!d) return 1;
if (~f[d][fl][fr][lead]) return f[d][fl][fr][lead];
ll res = 0;
int lb = fl ? ml[d] : 0, rb = fr ? mr[d] : 1;
for (int y = 0; y <= rb; ++y) {
for (int x = lb; x <= y; ++x) {
if (lead && x != y) continue;
res = (res + dfs(d - 1, fl & (x == lb), fr & (y == rb), lead && y == 0)) % mod;
}
}
return f[d][fl][fr][lead] = res;
}
void solve() {
memset(f, -1, sizeof f);
ll l, r;
cin >> l >> r;
while (l) {
ml[++L] = l & 1;
l >>= 1;
}
while (r) {
mr[++R] = r & 1;
r >>= 1;
}
cout << dfs(R, 1, 1, 1) % mod;
}