zoukankan      html  css  js  c++  java
  • Atcoder Grand Contest 005 题解

    A - STring

    用一个栈模拟即可。

    //waz
    #include <bits/stdc++.h>
     
    using namespace std;
     
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define ALL(x) (x).begin(), (x).end()
    #define SZ(x) ((int)((x).size()))
     
    typedef pair<int, int> PII;
    typedef vector<int> VI;
    typedef long long int64;
    typedef unsigned int uint;
    typedef unsigned long long uint64;
     
    #define gi(x) ((x) = F())
    #define gii(x, y) (gi(x), gi(y))
    #define giii(x, y, z) (gii(x, y), gi(z))
     
    int F()
    {
    	char ch;
    	int x, a;
    	while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
    	if (ch == '-') ch = getchar(), a = -1;
    	else a = 1;
    	x = ch - '0';
    	while (ch = getchar(), ch >= '0' && ch <= '9')
    		x = (x << 1) + (x << 3) + ch - '0';
    	return a * x;
    }
     
    const int N = 2e5 + 10;
     
    char str[N], stk[N];
     
    int n, tp;
     
    int main()
    {
    	scanf("%s", str + 1);
    	n = strlen(str + 1);
    	for (int i = 1; i <= n; ++i)
    	{
    		if (tp > 0 && stk[tp] == 'S' && str[i] == 'T') --tp;
    		else stk[++tp] = str[i];
    	}
    	printf("%d
    ", tp);
    	return 0;
    }
    

      

    B - Minimum Sum

    分治一下,计算一个数作为最小值的贡献。

    //waz
    #include <bits/stdc++.h>
     
    using namespace std;
     
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define ALL(x) (x).begin(), (x).end()
    #define SZ(x) ((int)((x).size()))
     
    typedef pair<int, int> PII;
    typedef vector<int> VI;
    typedef long long int64;
    typedef unsigned int uint;
    typedef unsigned long long uint64;
     
    #define gi(x) ((x) = F())
    #define gii(x, y) (gi(x), gi(y))
    #define giii(x, y, z) (gii(x, y), gi(z))
     
    int F()
    {
    	char ch;
    	int x, a;
    	while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
    	if (ch == '-') ch = getchar(), a = -1;
    	else a = 1;
    	x = ch - '0';
    	while (ch = getchar(), ch >= '0' && ch <= '9')
    		x = (x << 1) + (x << 3) + ch - '0';
    	return a * x;
    }
     
    const int N = 2e5 + 10;
     
    int a[N];
     
    long long ans;
     
    void solve(int l, int r)
    {
    	if (l == r)
    	{
    		ans += a[l];
    		return;
    	}
    	long long res = 0;
    	int mid = (l + r) >> 1;
    	vector<int> L, R;
    	for (int i = mid; i >= l; --i)
    	{
    		if (!SZ(L) || a[L[SZ(L) - 1]] > a[i])
    			L.pb(i);
    	}
    	for (int i = mid + 1; i <= r; ++i)
    	{
    		if (!SZ(R) || a[R[SZ(R) - 1]] > a[i])
    			R.pb(i);
    	}
    	L.pb(l - 1);
    	R.pb(r + 1);
    	for (int i = 0, j = 0; i < SZ(L) - 1; ++i)
    	{
    		while (a[R[j]] > a[L[i]] && j < SZ(R) - 1) ++j;
    		res += 1LL * (R[j] - mid - 1) * (L[i] - L[i + 1]) * a[L[i]];
    	}
    	for (int i = 0, j = 0; i < SZ(R) - 1; ++i)
    	{
    		while (a[R[i]] < a[L[j]] && j < SZ(L) - 1) ++j;
    		res += 1LL * (mid - L[j]) * (R[i + 1] - R[i]) * a[R[i]];
    	}
    	ans += res;
    	solve(l, mid);
    	solve(mid + 1, r);
    }
     
    int n;
     
    int main()
    {
    	gi(n);
    	for (int i = 1; i <= n; ++i) gi(a[i]);
    	solve(1, n);
    	printf("%lld
    ", ans);
    	return 0;
    }
    

      

    C - Tree Restoring

    先把直径找出来,其它的挂在直径上就好了。

    //waz
    #include <bits/stdc++.h>
     
    using namespace std;
     
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define ALL(x) (x).begin(), (x).end()
    #define SZ(x) ((int)((x).size()))
     
    typedef pair<int, int> PII;
    typedef vector<int> VI;
    typedef long long int64;
    typedef unsigned int uint;
    typedef unsigned long long uint64;
     
    #define gi(x) ((x) = F())
    #define gii(x, y) (gi(x), gi(y))
    #define giii(x, y, z) (gii(x, y), gi(z))
     
    int F()
    {
    	char ch;
    	int x, a;
    	while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
    	if (ch == '-') ch = getchar(), a = -1;
    	else a = 1;
    	x = ch - '0';
    	while (ch = getchar(), ch >= '0' && ch <= '9')
    		x = (x << 1) + (x << 3) + ch - '0';
    	return a * x;
    }
     
    int n, a[110];
     
    int main()
    {
    	gi(n);
    	for (int i = n; i; --i) gi(a[i]);
    	sort(a + 1, a + n + 1);
    	reverse(a + 1, a + n + 1);
    	int len = a[1];
    	int mn = len / 2 + 1;
    	for (int i = len; i > len / 2; --i)
    	{
    		int cnt = 0;
    		for (int j = 1; j <= n; ++j)
    		{
    			if (a[j] == i) ++cnt, a[j] = 0;
    			if (cnt == 2) break;
    		}
    		if (cnt < 2)
    		{
    			puts("Impossible");
    			return 0;
    		}
    	}
    	if (!(len & 1))
    	{
    		mn = len / 2;
    		int cnt = 0;
    		for (int j = 1; j <= n; ++j)
    		{
    			if (a[j] == (len >> 1)) ++cnt, a[j] = 0;
    			if (cnt == 1) break;
    		}
    		if (cnt < 1)
    		{
    			puts("Impossible");
    			return 0;
    		}
    	}
    	for (int i = 1; i <= n; ++i)
    		if (a[i] && a[i] <= mn)
    		{
    			puts("Impossible");
    			return 0;
    		}
    	puts("Possible");
    	return 0;
    }
    

      

    D - ~K Perm Counting

    我们发现可以放置的可以画出一个二分图,然后容斥一下就好了。

    //waz
    #include <bits/stdc++.h>
     
    using namespace std;
     
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define ALL(x) (x).begin(), (x).end()
    #define SZ(x) ((int)((x).size()))
     
    typedef pair<int, int> PII;
    typedef vector<int> VI;
    typedef long long int64;
    typedef unsigned int uint;
    typedef unsigned long long uint64;
     
    #define gi(x) ((x) = F())
    #define gii(x, y) (gi(x), gi(y))
    #define giii(x, y, z) (gii(x, y), gi(z))
     
    int F()
    {
    	char ch;
    	int x, a;
    	while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
    	if (ch == '-') ch = getchar(), a = -1;
    	else a = 1;
    	x = ch - '0';
    	while (ch = getchar(), ch >= '0' && ch <= '9')
    		x = (x << 1) + (x << 3) + ch - '0';
    	return a * x;
    }
     
    const int mod = 924844033;
     
    int f[2010][2010][2], g[2010], t[2010], ans;
     
    int main()
    {
    	int n, k;
    	gii(n, k);
    	f[0][0][0] = 1;
    	for (int i = 1; i <= n; ++i)
    	{
    		for (int j = 0; j <= n; ++j)
    		{
    			f[i][j][0] = (f[i][j][0] + f[i - 1][j][0]) % mod;
    			f[i][j][0] = (f[i][j][0] + f[i - 1][j][1]) % mod;
    			if (j) f[i][j][1] = f[i - 1][j - 1][0];
    		}
    	}
    	g[0] = 1;
    	for (int i = 1; i <= k; ++i)
    	{
    		int len = (n - i) / k;
    		for (int i = 0; i <= n; ++i)
    			t[i] = g[i], g[i] = 0;
    		for (int j = 0; j <= len; ++j)
    			for (int l = 0; l <= n - j; ++l)
    				g[j + l] = (g[j + l] + 1LL * t[l] * (f[len][j][0] + f[len][j][1])) % mod;
    		for (int i = 0; i <= n; ++i)
    			t[i] = g[i], g[i] = 0;
    		for (int j = 0; j <= len; ++j)
    			for (int l = 0; l <= n - j; ++l)
    				g[j + l] = (g[j + l] + 1LL * t[l] * (f[len][j][0] + f[len][j][1])) % mod;
    	}
    	for (int i = n, fac = 1, j = (n & 1) ^ 1; ~i; --i, fac = 1LL * fac * (n - i) % mod, j ^= 1)
    	{
    		if (j) ans = (ans + 1LL * g[i] * fac) % mod;
    		else ans = (ans - 1LL * g[i] * fac) % mod;
    	}
    	if (ans < 0) ans += mod;
    	printf("%d
    ", ans);
    	return 0;
    }
    

      

    E - Sugigma: The Showdown

     如果有一条A中的边在B中长度大于2,只要A走到肯定赢,A能走到的点就是A要在B之前走到,算一下就好了。

    //waz
    #include <bits/stdc++.h>
     
    using namespace std;
     
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define ALL(x) (x).begin(), (x).end()
    #define SZ(x) ((int)((x).size()))
     
    typedef pair<int, int> PII;
    typedef vector<int> VI;
    typedef long long int64;
    typedef unsigned int uint;
    typedef unsigned long long uint64;
     
    #define gi(x) ((x) = F())
    #define gii(x, y) (gi(x), gi(y))
    #define giii(x, y, z) (gii(x, y), gi(z))
     
    int F()
    {
    	char ch;
    	int x, a;
    	while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
    	if (ch == '-') ch = getchar(), a = -1;
    	else a = 1;
    	x = ch - '0';
    	while (ch = getchar(), ch >= '0' && ch <= '9')
    		x = (x << 1) + (x << 3) + ch - '0';
    	return a * x;
    }
     
    const int N = 2e5 + 10;
     
    int n;
     
    VI A[N], B[N];
     
    int fa[N], in[N], out[N], dep[N], dfs_clock;
     
    void dfsB(int u)
    {
    	in[u] = ++dfs_clock;
    	for (auto v : B[u])
    	{
    		if (v == fa[u]) continue;
    		fa[v] = u;
    		dep[v] = dep[u] + 1;
    		dfsB(v);
    	}
    	out[u] = dfs_clock;
    }
     
    bool check(int u, int v)
    {
    	if (in[u] <= in[v] && in[v] <= out[u])
    	{
    		if (fa[v] == u) return 1;
    		if (fa[fa[v]] == u) return 1;
    		return 0;
     	}
     	if (in[v] <= in[u] && in[u] <= out[v])
    	{
    		if (fa[u] == v) return 1;
    		if (fa[fa[u]] == v) return 1;
    		return 0;
     	}
     	if (fa[u] == fa[v]) return 1;
     	return 0;
    }
     
    bool vis[N];
     
    int d[N];
     
    void bfsA(int s)
    {
    	static int q[N]; int l = 0, r = 0;
    	q[r++] = s; vis[s] = 1;
    	while (l < r)
    	{
    		int u = q[l++];
    		for (auto v : A[u])
    		{
    			if (vis[v]) continue;
    			d[v] = d[u] + 1;
    			if (d[v] < dep[v] && !vis[v])
    			{
    				vis[v] = 1;
    				q[r++] = v;
    			}
    		}
    	}
    }
     
    int rootA, rootB;
     
    bool win[N];
     
    int main()
    {
    	giii(n, rootA, rootB);
    	for (int i = 1; i < n; ++i)
    	{
    		int u, v;
    		gii(u, v);
    		A[u].pb(v);
    		A[v].pb(u);
    	}
    	for (int i = 1; i < n; ++i)
    	{
    		int u, v;
    		gii(u, v);
    		B[u].pb(v);
    		B[v].pb(u);
    	}
    	dfsB(rootB);
    	for (int i = 1; i <= n; ++i)
    	{
    		for (auto j : A[i])
    			if (!check(i, j)) win[i] = win[j] = 1;
    	}
    	bfsA(rootA);
    	int ans = 0;
    	for (int i = 1; i <= n; ++i)
    	{
    		if (vis[i] && win[i]) 
    		{
    			puts("-1");
    			return 0;
    		}
    		if (vis[i]) ans = max(ans, dep[i] * 2);
    	}
    	printf("%d
    ", ans);
    	return 0;
    }
    

      

    F - Many Easy Problems

    分开算每个点贡献,可以用容斥做,最后发现这个式子是一个卷积。NTT一下就好了。

    //waz
    #include <bits/stdc++.h>
     
    using namespace std;
     
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define ALL(x) (x).begin(), (x).end()
    #define SZ(x) ((int)((x).size()))
     
    typedef pair<int, int> PII;
    typedef vector<int> VI;
    typedef long long int64;
    typedef unsigned int uint;
    typedef unsigned long long uint64;
     
    #define gi(x) ((x) = F())
    #define gii(x, y) (gi(x), gi(y))
    #define giii(x, y, z) (gii(x, y), gi(z))
     
    int F()
    {
    	char ch;
    	int x, a;
    	while (ch = getchar(), (ch < '0' || ch > '9') && ch != '-');
    	if (ch == '-') ch = getchar(), a = -1;
    	else a = 1;
    	x = ch - '0';
    	while (ch = getchar(), ch >= '0' && ch <= '9')
    		x = (x << 1) + (x << 3) + ch - '0';
    	return a * x;
    }
     
    const int N = 1 << 20;
     
    const int mod = 924844033;
     
    const int g = 5;
     
    int fpow(int a, int x)
    {
    	int ret = 1;
    	for (; x; x >>= 1)
    	{
    		if (x & 1) ret = 1LL * ret * a % mod;
    		a = 1LL * a * a % mod;
    	}
    	return ret;
    }
     
    int n;
     
    vector<int> edge[N];
     
    int cnt[N], siz[N], fac[N], ifac[N];
     
    int C(int n, int m)
    {
    	if (n < m || m < 0) return 0;
    	return 1LL * fac[n] * ifac[n - m] % mod * ifac[m] % mod;
    }
     
    void dfs(int u, int fa)
    {
    	siz[u] = 1;
    	for (auto v : edge[u])
    	{
    		if (v == fa) continue;
    		dfs(v, u);
    		siz[u] += siz[v];
    	}
    	for (auto v : edge[u])
    	{
    		if (v == fa)
    		{
    			++cnt[n - siz[u]];
    			continue;
    		}
    		++cnt[siz[v]];
    	}
    }
     
    void dft(int *a, int n, int sig)
    {
    	for (int i = 0, j = 0; i < n; ++i)
    	{
    		if (i > j) swap(a[i], a[j]);
    		for (int l = n >> 1; (j ^= l) < l; l >>= 1);
    	}
    	for (int i = 1; i < n; i <<= 1)
    	{
    		int m = i << 1;
    		int w = fpow(g, (mod - 1) / m);
    		if (sig == -1) w = fpow(w, mod - 2);
    		for (int j = 0; j < n; j += m)
    		{
    			int v = 1;
    			for (int k = j; k < j + i; ++k, v = 1LL * v * w % mod)
    			{
    				int x = a[k], y = 1LL * a[k + i] * v % mod;
    				a[k] = (x + y) % mod;
    				a[k + i] = (x - y + mod) % mod;
    			}
    		}
    	}
    	if (sig == -1)
    	{
    		int invn = fpow(n, mod - 2);
    		for (int i = 0; i < n; ++i) a[i] = 1LL * a[i] * invn % mod;
    	}
    }
     
    int main()
    {
    	gi(n);
    	for (int i = 1; i < n; ++i)
    	{
    		int u, v;
    		gii(u, v);
    		edge[u].pb(v);
    		edge[v].pb(u);
    	}
    	dfs(1, 0);
    	fac[0] = 1;
    	for (int i = 1; i <= n; ++i) fac[i] = 1LL * fac[i - 1] * i % mod;
    	ifac[n] = fpow(fac[n], mod - 2);
    	for (int i = n; i; --i) ifac[i - 1] = 1LL * ifac[i] * i % mod;
    	static int f[N], g[N];
    	for (int i = 0; i <= n; ++i) g[i] = ifac[n - i];
    	for (int i = 0; i <= n; ++i) f[i] = 1LL * cnt[i] * fac[i] % mod;
    	int m = 1;
    	for (; m <= (n << 1); m <<= 1);
    	dft(f, m, 1), dft(g, m, 1);
    	for (int i = 0; i < m; ++i) f[i] = 1LL * f[i] * g[i] % mod;
    	dft(f, m, -1);
    	for (int k = 1; k <= n; ++k)
    	{
    		int ans = n;
    		ans = 1LL * ans * C(n, k) % mod;
    		ans = (ans - 1LL * ifac[k] * f[n + k]) % mod;
    		if (ans < 0) ans += mod;
    		printf("%d
    ", ans);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    数组
    对象
    js继承
    js原型原型链
    es6(初级)
    canvas背景
    Angular.js进阶
    Angular.js-2入门
    angular.js-1初识
    js之广告
  • 原文地址:https://www.cnblogs.com/AnzheWang/p/9621469.html
Copyright © 2011-2022 走看看