• Atcoder Grand Contest 002 题解


    A - Range Product

    经过0答案肯定是0,都是正数肯定是正数,都是负数的话就奇负偶正。

    //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 a, b;
     
    int main()
    {
    	gii(a, b);
    	if (a <= 0 && b >= 0) puts("Zero");
    	else
    	{
    		if (a > 0) puts("Positive");
    		else
    		{
    			if ((b - a + 1) & 1) puts("Negative");
    			else puts("Positive");
    		}
    	} 
    }
    

      

    B - Box and Ball

    模拟,顺序模拟判断用一个bool数组存这个点红球可不可能在这里,直接扫过去就好了。

    //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, m, x[N], y[N];
     
    int cnt[N];
     
    bool can[N];
     
    int main()
    {
    	gii(n, m);
    	for (int i = 1; i <= m; ++i)
    		gii(x[i], y[i]);
    	for (int i = 1; i <= n; ++i) cnt[i] = 1;
    	can[1] = 1;
    	for (int i = 1; i <= m; ++i)
    	{
    		if (can[x[i]])
    		{
    			if (cnt[x[i]] == 1)
    				can[x[i]] = 0;
    			can[y[i]] = 1;
    		}
    		--cnt[x[i]];
    		++cnt[y[i]];
    	}
    	int ans = 0;
    	for (int i = 1; i <= n; ++i)
    		if (can[i]) ++ans;
    	printf("%d
    ", ans);
    	return 0;
    }
    

      

    C - Knot Puzzle

    找出最长的a[i]+a[i+1],如果大于等于l,就从两头一直删到这里,否则无解。

    //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 a[100010];
     
    int n, l;
     
    int main()
    {
    	gii(n, l);
    	for (int i = 1; i <= n; ++i) gi(a[i]);
    	int j = 1;
    	for (int i = 2; i < n; ++i)
    		if (a[i] + a[i + 1] > a[j] + a[j + 1])
    			j = i;
    	if (a[j] + a[j + 1] < l)
    	{
    		puts("Impossible");
    		return 0;
    	}
    	puts("Possible");
    	for (int i = 1; i < j; ++i)
    		printf("%d
    ", i);
    	for (int i = n - 1; i >= j; --i)
    		printf("%d
    ", i);
    	return 0;
    }
    

      

    D - Stamp Rally

    整体二分,用撤销并查集维护即可。

    //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;
     
    struct query
    {
    	int x, y, z, id;
    };
     
    int ans[N];
     
    int n, m;
     
    int a[N], b[N];
     
    struct info
    {
    	int fa, siz;
    } f[N];
     
    struct item
    {
    	int x, y;
    	info a, b;
    } stk[N];
     
    int tp;
     
    int find(int x) { return f[x].fa == x ? x : find(f[x].fa); }
     
    void unit(int x, int y)
    {
    	x = find(x), y = find(y);
    	if (x == y) return;
    	if (f[x].siz < f[y].siz) swap(x, y);
    	stk[++tp] = (item) {x, y, f[x], f[y]};
    	f[y].fa = x, f[x].siz += f[y].siz;
    }
     
    void undo(int beg)
    {
    	while (tp != beg)
    	{
    		f[stk[tp].x] = stk[tp].a;
    		f[stk[tp].y] = stk[tp].b;
    		--tp;
    	}
    }
     
    void solve(int l, int r, vector<query> v)
    {
    	if (l == r)
    	{
    		for (auto x : v)
    			ans[x.id] = l;
    		return;
    	}
    	int mid = (l + r) >> 1;
    	int now = tp;
    	for (int i = l; i <= mid; ++i) unit(a[i], b[i]);
    	vector<query> L, R;
    	L.clear(), R.clear();
    	for (auto x : v)
    	{
    		int siz = f[find(x.x)].siz;
    		if (find(x.x) != find(x.y))
    			siz += f[find(x.y)].siz;
    		if (siz >= x.z)
    			L.pb(x);
    		else
    			R.pb(x);
    	}
    	solve(mid + 1, r, R);
    	undo(now);
    	solve(l, mid, L);
    }
     
    int main()
    {
    	gii(n, m);
    	for (int i = 1; i <= n; ++i) f[i] = (info) {i, 1};
    	for (int i = 1; i <= m; ++i)
    		gii(a[i], b[i]);
    	int Q;
    	gi(Q);
    	vector<query> v; v.clear();
    	for (int i = 1; i <= Q; ++i)
    	{
    		int x, y, z;
    		giii(x, y, z);
    		v.pb((query){x, y, z, i});
    	}
    	solve(1, m, v);
    	for (int i = 1; i <= Q; ++i)
    		printf("%d
    ", ans[i]);
    }
    

      

    E - Candy Piles

    把决策表画出来,我们发现一个人选择一种删除方式,另一个就选另一种,也就是沿着x=y的斜线走,最后只要有一个方向能让先手赢,先手肯定会走那一边,否则就是后手必胜。

    //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];
     
    int main() 
    {
    	scanf("%d", &n);
    	for (int i = 1; i <= n; ++i) scanf("%d", a + i);
    	sort(a + 1, a + n + 1);
    	reverse(a + 1, a + n + 1);
    	for (int i = 1; i <= n; ++i)
    	{
    		if (i + 1 > a[i + 1])
    		{
    			int j = i + 1, ans = 0;
    			for (; a[j] == i; ++j) ans ^= 1;
    			if ((ans || ((a[i] - i) & 1))) puts("First");
    			else puts("Second");
    			break;
    		}
    	}
    }
    

      

    F - Leftmost Ball

    我们发现令白球的编号是1...n,保证编号小的在前面,只要算出这个方案数乘上n!,我们发现这是个特殊的拓扑图,求拓扑序方案数,一个n^2dp就好了。

    //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 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 f[2010][2010], n, k, fac[2010 * 2010], ifac[2010 * 2010];
    
    int C(int n, int m)
    {
    	if (n < m || m < 0) return 0;
    	return 1LL * fac[n] * ifac[m] % mod * ifac[n - m] % mod;
    }
    
    int get(int x, int y)
    {
    	return C(x + y, y);
    }
    
    int main()
    {
    	gii(n, k);
    	if (k == 1)
    	{
    		puts("1");
    		return 0;
    	}
    	f[0][0] = 1;
    	fac[0] = 1;
    	for (int i = 1; i <= (n + 2) * (k + 2); ++i) fac[i] = 1LL * fac[i - 1] * i % mod;
    	ifac[(n + 2) * (k + 2)] = fpow(fac[(n + 2) * (k + 2)], mod - 2);
    	for (int i = (n + 2) * (k + 2); i; --i) ifac[i - 1] = 1LL * ifac[i] * i % mod;
    	for (int i = 0; i <= n; ++i)
    		for (int j = i; j <= n; ++j)
    		{
    			
    			if (i) f[i][j] = (f[i][j] + f[i - 1][j]) % mod;
    			if (j) f[i][j] = (f[i][j] + 1LL * f[i][j - 1] * get((j - 1) * (k - 1) + i, k - 2)) % mod;
    			//cerr << "get = " << get(j * (k - 1), k - 2) << endl;
    		}
    	printf("%d
    ", int((1LL * f[n][n] * fac[n]) % mod));
    	return 0;
    }
    

      

  • 相关阅读:
    深度解析MVC3中的ModelValidator及相关unobtrusiveJs的验证(一)
    深度解析Asp.net中的验证和Mvc对它的继承
    C# WebBrowser保存页面为图片
    Vue-axios需要注意的几个点
    C# 为什么说事件是一种特殊的委托
    C# event 事件-2
    C# event 事件
    初始Redis与简单使用
    泛型的运用(用于查询数据后DataTable转实体类)
    C# 初识接口 Interface
  • 原文地址:https://www.cnblogs.com/AnzheWang/p/9608962.html
Copyright © 2020-2023  润新知