1. 程式人生 > >Atcoder Grand Contest 002 題解

Atcoder Grand Contest 002 題解

push_back 個人選擇 first box 可能 getc 等於 clear const

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\n", 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\n", i);
	for (int i = n - 1; i >= j; --i)
		printf("%d\n", 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\n", 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\n", int((1LL * f[n][n] * fac[n]) % mod));
	return 0;
}

  

Atcoder Grand Contest 002 題解