zoukankan      html  css  js  c++  java
  • 题解CF 12 月杂题选做

    2022-01-02

    大概都是些2021-12 Codeforces 的比赛中过得比较少但没那么少的题。

    1623D [4]

    首先找到循环节,假设长度为 \(L\),然后设答案为 \(E\),中间有 \(k\) 个位置可以搞到。有 \(E=(1-(1-p)^k)(E+L)+\sum (i-1)p(1-p)^{q-1}\)。后面那一坨就代表在中间停下的期望。然后解方程模拟即可。

    /*
    Time : 2022/01/02 11:09 
    Author : Gemini7X
    Problem : https://codeforces.com/contest/1623/problem/D
    */
    #include <bits/stdc++.h>
    #define pii pair<int, int>
    #define mp make_pair
    #define F first
    #define S second
    using namespace std;
    const int maxn = 200005, mod = 1e9 + 7;
    int add(int a, int b) { return a + b >= mod ? a + b - mod : a + b; }
    int dec(int a, int b) { return a - b < 0 ? a - b + mod : a - b; }
    int mul(int a, int b) { return 1ll * a * b % mod; }
    int ksm(int a, int b = mod - 2) { int ret = 1; for (; b; b >>= 1, a = mul(a, a)) if (b & 1) ret = mul(ret, a); return ret; }
    int n, m, rb, cb, rd, cd, p;
    pii stk[maxn << 2];
    int top;
    void run(int &x, int &y, int dx, int dy) {
    	x += dx; y += dy;
    }
    void work(int x, int y, int &dx, int &dy) {
    	if (x == 1 && dx == -1) dx = -dx;
    	if (x == n && dx == 1) dx = -dx;
    	if (y == 1 && dy == -1) dy = -dy;
    	if (y == m && dy == 1) dy = -dy;
    }
    void solve() {
    	cin >> n >> m >> rb >> cb >> rd >> cd >> p;
    	p = mul(p, ksm(100));
    	int x = rb, y = cb, dx = 1, dy = 1; top = 0;
    	work(x, y, dx, dy);
    	int ux = dx, uy = dy;
    	while (1) {
    		stk[++top] = mp(x, y);
    		run(x, y, dx, dy);
    		work(x, y, dx, dy);
    		if (x == rb && y == cb && dx == ux && dy == uy) break;
    	}
    	int k = 0, ans = 0;
    	for (int i = 1; i <= top; i++) {
    		x = stk[i].F, y = stk[i].S;
    		if (x == rd || y == cd) {
    			ans = add(ans, mul(mul(p, i - 1), ksm(dec(1, p), k)));
    			k++;
    		}
    	}
    	ans = add(ans, mul(top, ksm(dec(1, p), k)));
    	printf("%d\n", mul(ans, ksm(dec(1, ksm(dec(1, p), k)))));
    }
    int main() {
    	int T; cin >> T; while (T--) solve();
    	return 0;
    }
    

    1623E [5]

    一开始有个误区就是要按a,b,c,...的顺序扩,其实不用。先处理出double了之后会更优的节点,这个可以通过处理 in-order 来解决。然后考虑一个贪心,还是按照 in-order 来 dfs,在每个节点记录一个 cost 代表 double 了之后有一个没有 double 的祖先要被处理。如果 cost 大于 k 了也就不需要管了,否则先遍历左儿子,假设左儿子被 double 了,那么这个点也一定要被 double。否则假设这个点是 good 的,那么就可以 double 它。然后是一步很关键的点,只有当这个点被 double 了才可以取遍历其右儿子,否则如果右子树内有点被 double,那么这个点也要被 double,而这个点之前没有被 double 一定是因为它不优,那么这样最后的答案也就不优了。所以在遍历右儿子的时候已经可以把 cost 设成 1,从新开始遍历一棵树了。

    /*
    Time : 2022/01/02 12:50
    Author : Gemini7X
    Problem : https://codeforces.com/contest/1623/problem/E
    */
    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 200005;
    int n, k;
    char s[maxn];
    int ls[maxn], rs[maxn];
    int stk[maxn], top;
    bool good[maxn], mark[maxn];
    void dfs(int u) {
    	if (ls[u]) dfs(ls[u]);
    	stk[++top] = u;
    	if (rs[u]) dfs(rs[u]); 
    }
    void get_ans(int u, int cost) {
    	if (cost > k) return;
    	if (ls[u]) get_ans(ls[u], cost + 1);
    	if (mark[ls[u]]) mark[u] = 1;
    	else if (good[u]) mark[u] = 1, k -= cost;
    	if (rs[u] && mark[u]) get_ans(rs[u], 1);
    }
    int main() {
    	scanf("%d%d", &n, &k);
    	scanf("%s", s + 1);
    	for (int i = 1; i <= n; i++) scanf("%d%d", ls + i, rs + i);
    	dfs(1);
    	int lst = s[stk[n]];
    	for (int i = n - 1; i >= 1; i--) {
    		if (s[stk[i]] != lst) {
    			if (s[stk[i]] < lst) good[stk[i]] = 1;
    			lst = s[stk[i]];
    		} else good[stk[i]] = good[stk[i + 1]];
    	}
    	get_ans(1, 1);
    	for (int i = 1; i <= n; i++) {
    		putchar(s[stk[i]]);
    		if (mark[stk[i]]) putchar(s[stk[i]]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    LightOJ 1132 Summing up Powers(矩阵快速幂)
    hdu 3804 Query on a tree (树链剖分+线段树)
    LightOJ 1052 String Growth && uva 12045 Fun with Strings (矩阵快速幂)
    uva 12304 2D Geometry 110 in 1! (Geometry)
    LA 3263 That Nice Euler Circuit (2D Geometry)
    2013 SCAUCPC Summary
    poj 3321 Apple Tree (Binary Index Tree)
    uva 11796 Dog Distance (几何+模拟)
    uva 11178 Morley's Theorem (2D Geometry)
    动手动脑
  • 原文地址:https://www.cnblogs.com/zcr-blog/p/15757295.html
Copyright © 2011-2022 走看看