zoukankan      html  css  js  c++  java
  • Codeforces Round #607 (Div. 1) Solution

    从这里开始

      我又不太会 div 1 A? 我菜爆了。。。

    Problem A Cut and Paste

      暴力模拟一下。

    Code

    #include <bits/stdc++.h>
    using namespace std;
    typedef bool boolean;
    
    const int N = 1e6 + 5;
    const int Mod = 1e9 + 7;
    
    int T;
    int x;
    int len;
    char s[N];
    
    int paste(int s1, int t1, int s2) {
    	int i = s2;
    	for (i = s2; i <= x && i - s2 + s1 <= t1; i++)
    		s[i] = s[i - s2 + s1];
    	return i;
    }
    
    void solve() {
    	scanf("%d", &x);
    	scanf("%s", s + 1);
    	len = strlen(s + 1);
    	int rlen = len;
    	for (int i = 1; i <= x; i++) {
    		int t = s[i] - '0' - 1;
    		len = ((i + (len - i) * 1ll * (t + 1)) % Mod + Mod) % Mod;
    		int qaq = rlen;
    		while (t--)
    			rlen = paste(i + 1, qaq, rlen + 1) - 1;
    	}
    	printf("%d
    ", len);
    }
    
    int main() {
    	scanf("%d", &T);
    	while (T--) {
    		solve();
    	}
    	return 0;
    }

    Problem B Beingawesomeism

      不难注意到答案不会超过 4.

    • 答案为 0,这个很 trivial
    • 答案小于等于 1 显然是存在一个边界被完全覆盖
    • 答案小于等于 2,存在一个 A 在角落或者完整的一行或一列为 A
    • 答案小于等于 3,存在 1 个 A 在边界上
    • 剩下的情况答案为 4

    Code

    #include <bits/stdc++.h>
    using namespace std;
    typedef bool boolean;
    
    const int N = 66;
    
    int T, n, m;
    char s[N][N];
    
    int count(int x1, int y1, int x2, int y2) {
    	int x = 0;
    	for (int i = x1; i <= x2; i++) {
    		for (int j = y1; j <= y2; j++) {
    			x += s[i][j] == 'A';
    		}
    	}
    	return x;
    }
    
    void solve() {
    	scanf("%d%d", &n, &m);
    	for (int i = 1; i <= n; i++) {
    		scanf("%s", s[i] + 1);
    	}
    	int c = count(1, 1, n, m);
    	if (!c) {
    		puts("MORTAL");
    		return;
    	}
    	if ((c == n * m)) {
    		puts("0");
    		return;
    	}
    	boolean havec = (s[1][1] == 'A' || s[n][1] == 'A' || s[1][m] == 'A' || s[n][m] == 'A');
    	int L = count(1, 1, n, 1);
    	int R = count(1, m, n, m);
    	if (L == n || R == n) {
    		puts("1");
    		return;
    	}
    	int U = count(1, 1, 1, m);
    	int D = count(n, 1, n, m);
    	if (U == m || D == m) {
    		puts("1");
    		return;
    	}
    	if (havec) {
    		puts("2");
    		return;
    	}
    	for (int i = 1; i <= n; i++) {
    		if (count(i, 1, i, m) == m) {
    			puts("2");
    			return;
    		}
    	}
    	for (int i = 1; i <= m; i++) {
    		if (count(1, i, n, i) == n) {
    			puts("2");
    			return;
    		}
    	}
    	if (L + R + U + D) {
    		puts("3");
    		return;
    	}
    	puts("4");
    }
    
    int main() {
    	scanf("%d", &T);
    	while (T--) {
    		solve();
    	}
    	return 0;
    }

    Problem C Jeremy Bearimy

      最大的话,显然以重心为根,答案为每个点的深度和

      最小的话,显然每个点的子树内至多有 1 个未匹配点,dp 即可。

    Code

    #include <bits/stdc++.h>
    using namespace std;
    typedef bool boolean;
    
    const int N = 6e5 + 5;
    
    #define ll long long
    #define pii pair<int, int>
    
    const ll llf = (signed ll) (~0ull >> 3);
    
    template <typename T>
    boolean vmin(T& a, T b) {
    	if (a > b) {
    		a = b;
    		return true;
    	}
    	return false;
    }
    
    int T;
    int n, n2;
    int sz[N];
    vector<pii> G[N];
    
    int get_sz(int p, int fa) {
    	sz[p] = 1;
    	for (auto E : G[p]) {
    		int e = E.first;
    		if (e == fa)
    			continue;
    		sz[p] += get_sz(e, p);
    	}
    	return sz[p];
    }
    
    int get_g(int p, int fa) {
    	for (auto E : G[p]) {
    		int e = E.first;
    		if (e == fa)
    			continue;
    		if (sz[e] > n) {
    			return get_g(e, p);
    		}
    	}
    	return p;
    }
    
    ll dep[N];
    void dfs(int p, int fa) {
    	for (auto E : G[p]) {
    		int e = E.first;
    		int w = E.second;
    		if (e == fa)
    			continue;
    		dep[e] = dep[p] + w;
    		dfs(e, p);
    	}
    }
    
    ll f[N][2];
    void dp(int p, int fa) {
    	static ll g[2];
    	f[p][0] = llf, f[p][1] = 0;
    	for (auto E : G[p]) {
    		int e = E.first;
    		int w = E.second;
    		if (e == fa)
    			continue;
    		dp(e, p);
    		g[0] = g[1] = llf;
    		vmin(g[0], f[p][0] + f[e][0]);
    		vmin(g[0], f[p][1] + f[e][1] + w);
    		vmin(g[1], f[p][0] + f[e][1] + w);
    		vmin(g[1], f[p][1] + f[e][0]);
    		f[p][0] = g[0];
    		f[p][1] = g[1];
    	}
    }
    
    void solve() {
    	scanf("%d", &n);
    	n2 = n << 1;
    	for (int i = 1; i <= (n << 1); i++) {
    		G[i].clear();
    	}
    	for (int i = 1, u, v, t; i < n2; i++) {
    		scanf("%d%d%d", &u, &v, &t);
    		G[u].emplace_back(v, t);
    		G[v].emplace_back(u, t);
    	}
    	get_sz(1, 0);
    	int g = get_g(1, 0);
    	dep[g] = 0;
    	dfs(g, 0);
    	ll ansmx = 0;
    	for (int i = 1; i <= n2; i++) {
    		ansmx += dep[i];
    	}
    	dp(g, 0);
    	printf("%lld %lld
    ", f[g][0], ansmx);
    }
    
    int main() {
    	scanf("%d", &T);
    	while (T--) {
    		solve();
    	}
    	return 0;
    }

    Problem D Miss Punyverse

      考虑如果子树内留下的决策不是已有的合法划分最多的一个,至多使答案增加 1,但这里会减少 1,因此子树内决策只用保留合法划分最多,且未结束划分的一块的和最大。

      然后 dp 即可。

    Code

    #include <bits/stdc++.h>
    using namespace std;
    typedef bool boolean;
    
    #define ll long long
    
    #define pii pair<int, ll>
    
    pii operator + (pii a, pii b) {
    	return pii(a.first + b.first, a.second + b.second);
    }
    
    const int N = 3005;
    
    int T, n, m;
    int sz[N];
    pii f[N][N];
    int a[N], b[N];
    vector<int> G[N];
    
    pii work(pii x) {
    	x.first += x.second > 0;
    	x.second = 0;
    	return x;
    }
    
    void dfs(int p, int fa) {
    	static pii g[N];
    	for (int i = 0; i <= m; i++)
    		f[p][i] = pii(-N, 0);
    	f[p][0] = pii(0, 0);
    	sz[p] = 0;
    	for (auto e : G[p]) {
    		if (e == fa)
    			continue;
    		dfs(e, p);
    		for (int i = 0; i <= sz[p] + sz[e] && i <= m; i++)
    			g[i] = pii(-N, 0);
    		for (int i = 0; i <= sz[p]; i++) {
    			for (int j = 0; j < sz[e] && i + j <= m; j++) {
    				g[i + j] = max(g[i + j], f[p][i] + f[e][j]);
    				if (j < m)
    					g[i + j + 1] = max(g[i + j + 1], f[p][i] + work(f[e][j]));
    			}
    		}
    		for (int i = 0; i <= sz[p] + sz[e] && i <= m; i++)
    			f[p][i] = g[i];
    		sz[p] += sz[e];
    	}
    	++sz[p];
    	for (int i = 0; i < sz[p]; i++) {
    		f[p][i].second += a[p] - b[p];
    	}
    }
    
    void solve() {
    	scanf("%d%d", &n, &m);
    	for (int i = 1; i <= n; i++) {
    		scanf("%d", b + i);
    	}
    	for (int i = 1; i <= n; i++) {
    		scanf("%d", a + i);
    	}
    	for (int i = 1; i <= n; i++)
    		G[i].clear();
    	for (int i = 1, u, v; i < n; i++) {
    		scanf("%d%d", &u, &v);
    		G[u].push_back(v);
    		G[v].push_back(u);
    	}
    	dfs(1, 0);
    	int ans = work(f[1][m - 1]).first;
    	printf("%d
    ", ans);
    }
    
    int main() {
    	scanf("%d", &T);
    	while (T--) {
    		solve();
    	}
    	return 0;
    }

    Problem E Kirchhoff's Current Loss

      这个 E 感觉挺简单的,可惜我没时间做了,sad.....

      考虑 $n$ 个电阻串联,答案为 $r$,这个很显然

      考虑 $n$ 个电阻并联,答案为 $n^2r$,证明考虑用均值不等式归纳。

      简单归纳一下可以发现,最终一定是等效于 $k$ 个电阻并联。

      然后 dp 即可。

    #include <bits/stdc++.h>
    using namespace std;
    typedef bool boolean;
    
    const int N = 2e5 + 5;
    
    int T;
    int n, m, r;
    char s[1000000];
    boolean ispar[N];
    vector<int> G[N];
    
    int newnode() {
    	++n;
    	G[n].clear();
    	ispar[n] = false;
    	return n;
    }
    
    int id[N];
    int build(char* &s) {
    	int p = newnode();
    	while (true) {
    		while (*s == ' ')
    			s++;
    		if (!*s || *s == ')')
    			return p;
    		if (*s == 'P') {
    			ispar[p] = true;
    		} else if (*s == 'S') {
    			ispar[p] = false;
    		} else if (*s == '(') {
    			G[p].push_back(build(++s));
    		} else if (*s == '*') {
    			G[p].push_back(newnode());
    			id[n] = ++m;
    		}
    		s++;
    	}
    	return p;
    }
    
    int f[N], g[N], R[N];
    void dfs(int p) {
    	if (G[p].empty()) {
    		f[p] = 1;
    		return;
    	}
    	if (!ispar[p]) {
    		f[p] = 1e9;
    		g[p] = -1;
    		for (auto e : G[p]) {
    			dfs(e);
    			if (f[e] < f[p]) {
    				f[p] = f[e];
    				g[p] = e; 
    			}
    		}
    	} else {
    		f[p] = 0;
    		for (auto e : G[p]) {
    			dfs(e);
    			f[p] += f[e];
    		}
    	}
    }
    
    void dfs1(int p) {
    	if (G[p].empty()) {
    		R[id[p]] = 1;
    		return;
    	}
    	if (ispar[p]) {
    		for (auto e : G[p])
    			dfs1(e);
    	} else {
    		dfs1(g[p]);
    	}
    }
    
    int main() {
    	scanf("%d", &T);
    	while (T--) {
    		n = m = 0;
    		scanf("%d", &r);
    		gets(s);
    		char* tmp = s;
    		build(tmp);
    		dfs(1);
    		long long v = 1ll * r * f[1];
    		for (int i = 1; i <= m; i++) {
    			R[i] = 0;
    		}
    		dfs1(1);
    		printf("REVOLTING");
    		for (int i = 1; i <= m; i++)
    			printf(" %lld", R[i] * v);
    		putchar('
    ');
    	}
    	return 0;
    }

    Problem F Intergalactic Sliding Puzzle

      考虑按顺时针的构成的环排列,不考虑空位置。

      注意到大环不会影响环排列,而空位置经过中间的隔板会做一个长度为 $2k + 1$ 的循环移位。

      不难发现必要条件是排列的逆序对个数位偶数个,因为这些循环移位均不会改变逆序对奇偶性。

      通过打表(或者阅读题解)可以构造把连续 3 个数循环位移的方案。

      然后简单构造一下就行了。

    Code

    #include <bits/stdc++.h>
    using namespace std;
    typedef bool boolean;
    
    const int N = 128;
    
    string operator * (string a, int t) {
    	string b = "";
    	for (int i = 0; i < t; i++)
    		b += a;
    	return b;
    }
    ostream& operator << (ostream& os, vector<int> p) {
    	for (auto x : p)
    		os << x << " ";
    	os << '
    ';
    	return os;
    }
    
    string sl("l"), sr("r"), su("u"), sd("d");
    
    int T, k, L, n;
    int x, y;
    vector<int> grid[2];
    vector<int> perm;
    
    void solve() {
    	cin >> k;
    	L = 2 * k + 1;
    	n = 4 * k + 1;
    	grid[0].resize(L);
    	grid[1].resize(L);
    	string _;
    	for (int i = 0; i < L; i++) {
    		cin >> _;
    		if (_[0] == 'E') {
    			grid[0][i] = -1;
    			x = 0, y = i;
    		} else {
    			grid[0][i] = stoi(_);
    		}
    	}
    	for (int i = 0; i < L; i++) {
    		cin >> _;
    		if (_[0] == 'E') {
    			grid[1][i] = -1;
    			x = 1, y = i;
    		} else {
    			grid[1][i] = stoi(_);
    		}
    	}
    	string ans = "";
    	while (x != 0 || y != k) {
    		if (x == 0) {
    			if (y < k) {
    				ans += 'r';
    				swap(grid[x][y], grid[x][y + 1]);
    				y++;
    			} else {
    				ans += 'l';
    				swap(grid[x][y], grid[x][y - 1]);
    				y--;
    			}
    		} else {
    			if (!y) {
    				ans += 'u';
    				swap(grid[x][y], grid[x - 1][y]);
    				x--;
    			} else {
    				ans += 'l';
    				swap(grid[x][y], grid[x][y - 1]);
    				y--;
    			}
    		}
    	}
    	perm.clear();
    	reverse(grid[1].begin(), grid[1].end());
    	for (auto x : grid[0])
    		if (x > 0)
    			perm.push_back(x);
    	for (auto x : grid[1])
    		if (x > 0)
    			perm.push_back(x);
    	for (auto &x : perm)
    		if (x > L)
    			x = n - (x - L) + 1;
    	int inv = 0;
    	for (int i = 0; i < n; i++) {
    		for (int j = i + 1; j < n; j++) {
    			if (perm[i] > perm[j]) {
    				inv ^= 1;
    			}
    		}
    	}
    	if (inv) {
    		cout << ("SURGERY FAILED") << '
    ';
    		return;
    	}
    	auto rotateL = [&] () {
    		rotate(perm.begin(), perm.begin() + 1, perm.end());
    		ans += "A";
    	};
    	auto rotateR = [&] () {
    		rotate(perm.begin(), perm.end() - 1, perm.end());
    		ans += "B";
    	};
    	auto shift3 = [&] () {
    		swap(perm[0], perm[2]);
    		swap(perm[1], perm[2]);
    		ans += "S";
    	};
    	string A = sr * k + sd + sl * (L - 1) + su + sr * k;
    	string B = sl * k + sd + sr * (L - 1) + su + sl * k;
    	string C = sr * k + sd + sl * k + su;
    	string D = sd + sr * k + su + sl * k;
    	string S = string("B") * (k - 1) + "CBCADD" + string("A") * (k - 1);
    	while (perm[0] != 1)
    		rotateR();
    	for (int i = 2; i <= n - 2; i++) {
    		int d = -1;
    		while (perm[0] != i)
    			d++, rotateL();
    		if (d & 1) {
    			if (perm[1] == 1) {
    				rotateR(), rotateR();
    				shift3(), shift3();
    				d--;
    				rotateL();
    			} else if (perm[2] == 1) {
    				rotateR();
    				shift3();
    				d++;
    				rotateL();
    				rotateL();
    			} else {
    				shift3();
    				rotateL();
    				d++;
    			}
    		}
    		while (d) {
    			rotateR(), rotateR();
    			shift3();
    			d -= 2;
    		}
    	}
    	while (perm[0] != 1)
    		rotateR();
    	ans += sr * k + sd;
    	cout << "SURGERY COMPLETE
    ";
    	cout << ans << '
    ';
    	cout << "A " << A << '
    ';
    	cout << "B " << B << '
    ';
    	cout << "C " << C << '
    ';
    	cout << "D " << D << '
    ';
    	cout << "S " << S << '
    ';
    	cout << "DONE
    ";
    }
    
    int main() {
    //	freopen("a.txt", "r", stdin);
    	ios::sync_with_stdio(false);
    	cin.tie(0), cout.tie(0);
    	cin >> T;
    	while (T--) {
    		solve();
    	}
    	return 0;
    }

  • 相关阅读:
    基于SSM框架web搜索功能的实现
    使用APICloud打包webapp
    mac如何运行vue项目
    前端和算法实现:给网站上加上自己的水印(以后用上)
    jQuery常用代码片段
    关于vscode的个人配置
    听说你想用git,安装一下咯
    vue创建项目的一种方法
    用js控制css动画效果@keyframes
    axios的封装和拦截
  • 原文地址:https://www.cnblogs.com/yyf0309/p/12063681.html
Copyright © 2011-2022 走看看