• AtCoder Grand Contest 009 题解


    A - Multiple Array

    倒着算要加多少就好了。

    //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 = 1e5 + 10;
     
    int n;
     
    long long a[N], b[N];
     
    int main()
    {
    	gi(n);
    	for (int i = 1; i <= n; ++i)
    		gii(a[i], b[i]);
    	long long add = 0;
    	for (int i = n; i; --i)
    	{
    		a[i] += add;
    		if (a[i] % b[i]) add += b[i] - a[i] % b[i], a[i] += b[i] - a[i] % b[i];
    	}
    	printf("%lld
    ", add);
    	return 0;
    }
    

      

    B - Tournament

    树形dp,把所有儿子的轮数从小到大排序,算一下自己最少要多少轮即可。

    //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[100010];
     
    VI edge[100010];
     
    int rd[100010];
     
    void dfs(int u)
    {
    	VI p;
    	for (auto v : edge[u])
    	{
    		dfs(v);
    		p.pb(rd[v]);
    	}
    	sort(ALL(p));
    	for (auto x : p)
    		rd[u] = max(rd[u], x), ++rd[u];
    }
     
    int main()
    {
    	gi(n);
    	for (int i = 2; i <= n; ++i) gi(a[i]), edge[a[i]].pb(i);
    	dfs(1);
    	printf("%d
    ", rd[1]);
    	return 0;
    }
    

      

    C - Division into Two

    列出dp方程,令A>=B,把可以取的位置丢进树状数组维护一下dp即可。

    //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 = 1e5 + 10, mod = 1e9 + 7;
     
    int n;
     
    int64 A, B, S[N];
     
    int lf[N], f[N], g[N];
     
    int t[N];
     
    void add(int x, int v) { for (++x; x <= n + 1; x += x & -x) t[x] = (t[x] + v) % mod; }
     
    int query(int x) { int v = 0; for (++x; x; x -= x & -x) v = (v + t[x]) % mod; return v; }
     
    int main()
    {
    	gi(n);
    	scanf("%lld%lld", &A, &B);
    	if (A < B) swap(A, B);
    	for (int i = 1; i <= n; ++i) scanf("%lld", S + i); S[0] = -A;
    	++n; S[n] = S[n - 1] + A;
    	lf[1] = 1;
    	for (int i = 2; i <= n; ++i) if (S[i] >= S[i - 1] + B) lf[i] = lf[i - 1]; else lf[i] = i;
    	f[0] = 1;
    	add(0, f[0]);
    	for (int i = 1; i <= n; ++i)
    	{
    		int k = upper_bound(S + 1, S + i + 1, S[i] - A) - S - 1;
    		int j = lf[i - 1] - 1;
    		if (S[i] - S[i - 1] >= A) f[i] = f[i - 1];
    		if (i >= 2 && min(i - 2, k) >= j - 1) (f[i] += (query(min(i - 2, k)) - query(j - 1) + mod) % mod) %= mod;
    		if (i < n && S[i + 1] - S[i - 1] >= B) add(i, f[i]);
    	}
    	printf("%d
    ", f[n]);
    	return 0;
    }
    

      

    D - Uninity

    树分治是上界,也就是log,当有两个点是第k次标号,中间肯定要有一个k+1,用这个进行dp,算一下每个点的所有儿子令它最大是多少就好了。

    //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 = 1e5 + 10;
     
    VI edge[N];
     
    int n, bit[N], f[N];
     
    void dfs(int u, int fa)
    {
    	int l = 0;
    	for (auto v : edge[u])
    	{
    		if (v == fa) continue;
    		dfs(v, u);
    		l |= bit[u] & bit[v];
    		bit[u] |= bit[v];
    	}
    	if (!bit[u]) bit[u] = 1;
    	else
    	{
    		while ((1 << f[u]) < l || ((1 << f[u]) & bit[u])) ++f[u];
    		bit[u] = ((bit[u] >> f[u]) << f[u]) | (1 << f[u]);
    	}
    	f[0] = max(f[0], f[u]);
    }
     
    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);
    	printf("%d
    ", f[0]);
    	return 0;
    }
    

      

    E - Eternal Average

    转换为k叉树模型,发现最后要求的是一个符合条件序列的个数,dp一下即可。

    //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 = 1e9 + 7;
     
    int n, m, k, ans;
     
    int f[2][2010][2], sum[2010];
     
    int main()
    {
    	giii(n, m, k);
    	--m, --k;
    	for (int i = 1; i <= k; ++i) f[0][i][1] = 1;
    	f[0][0][0] = 1;
    	for (int i = 0; i <= n; ++i) 
    		if (k - i <= m && i % k == n % k && (k - i) % k == m % k) ans = (ans + f[0][i][1]) % mod;
    	int now = 0;
    	for (int i = 2; i <= max(n, m) * 2; ++i)
    	{
    		now ^= 1;
    		for (int j = 0; j <= n; ++j) sum[j + 1] = (sum[j] + (f[now ^ 1][j][0] + f[now ^ 1][j][1]) % mod) % mod;
    		for (int j = 0; j <= n; ++j)
    		{
    			f[now][j][0] = (sum[j + 1] - sum[j] + mod) % mod;
    			f[now][j][1] = (sum[j] - sum[max(0, j - k)] + mod) % mod;
    		}
    		for (int j = 0; j <= n; ++j)
    			if (k * i - j <= m && j % k == n % k && (k * i - j) % k == m % k) ans = (ans + f[now][j][1]) % mod;
    		//cerr << ans << endl;
    	}
    	printf("%d
    ", ans);
    }
    

      

  • 相关阅读:
    python实现简单爬虫功能
    python re group()
    [转载]python 详解re模块
    Python 异常处理
    Python中os和shutil模块实用方法集锦
    Python中os和shutil模块实用方法集锦
    关于selenium IDE找不到元素
    关于selenium IDE找不到元素
    关于selenium IDE找不到元素
    js模拟点击事件实现代码
  • 原文地址:https://www.cnblogs.com/AnzheWang/p/9641993.html
Copyright © 2020-2023  润新知