# AtCoder Grand Contest 002

## A - Range Product

#include <cstdio>

int A, B;

int main() {
scanf("%d%d", &A, &B);
if (A <= 0 && B >= 0) puts("Zero");
else if (A > 0 || (B - A) & 1) puts("Positive");
else puts("Negative");
return 0;
}


## B - Box and Ball

#include <cstdio>

const int MN = 100005;

int N, M, Ans;
int num[MN], typ[MN];

int main() {
scanf("%d%d", &N, &M);
for (int i = 1; i <= N; ++i)
num[i] = 1, typ[i] = i == 1;
for (int i = 1; i <= M; ++i) {
int x, y;
scanf("%d%d", &x, &y);
if (num[x] == 1) {
if (typ[x] == 1) typ[y] = 1;
else if (typ[x] == 2) typ[y] = 2;
typ[x] = 0;
} else if (typ[x] != 0) typ[x] = typ[y] = 2;
--num[x], ++num[y];
}
for (int i = 1; i <= N; ++i) if (typ[i]) ++Ans;
printf("%d\n", Ans);
return 0;
}


## C - Knot Puzzle

#include <cstdio>

const int MN = 100005;

int N, L, A[MN];

int main() {
scanf("%d%d", &N, &L);
for (int i = 1; i <= N; ++i) scanf("%d", &A[i]);
int ok = 0;
for (int i = 1; i < N; ++i) if (A[i] + A[i + 1] >= L) ok = i;
if (!ok) return puts("Impossible"), 0;
puts("Possible");
for (int i = 1; i < ok; ++i) printf("%d\n", i);
for (int i = N - 1; i >= ok; --i) printf("%d\n", i);
return 0;
}


## D - Stamp Rally

#include <cstdio>
#include <algorithm>

const int MN = 100005, MM = 100005, MQ = 100005;

int N, M, a[MM], b[MM];
int Q, x[MQ], y[MQ], z[MQ], p[MQ], ans[MQ];

int par[MN], siz[MN], stk[MN], tp;
inline int fp(int u) {
while (par[u]) u = par[u];
return u;
}
inline void merge(int u, int v) {
u = fp(u), v = fp(v);
if (u == v) return ;
if (siz[u] < siz[v]) std::swap(u, v);
par[v] = u, siz[u] += siz[v];
stk[++tp] = v;
}
inline void undo(int k) {
while (tp > k) {
int v = stk[tp--];
siz[par[v]] -= siz[v];
par[v] = 0;
}
}

int tmp[MQ];
void Solve(int l, int r, int s, int t) {
if (s > t) {
for (int i = l; i <= r; ++i) merge(a[i], b[i]);
return ;
}
if (l == r) {
for (int i = s; i <= t; ++i) ans[p[i]] = l;
merge(a[l], b[l]);
return ;
}
int mid = (l + r) >> 1, now = tp;
for (int i = l; i <= mid; ++i) merge(a[i], b[i]);
int s_ = s, t_ = t;
for (int i = s; i <= t; ++i) {
int u = fp(x[p[i]]), v = fp(y[p[i]]);
int sum = u == v ? siz[u] : siz[u] + siz[v];
if (sum >= z[p[i]]) tmp[s_++] = p[i];
else tmp[t_--] = p[i];
}
undo(now);
for (int i = s; i <= t; ++i) p[i] = tmp[i];
Solve(l, mid, s, t_);
Solve(mid + 1, r, s_, t);
}

int main() {
scanf("%d%d", &N, &M);
for (int i = 1; i <= M; ++i) scanf("%d%d", &a[i], &b[i]);
scanf("%d", &Q);
for (int i = 1; i <= Q; ++i) scanf("%d%d%d", &x[i], &y[i], &z[i]), p[i] = i;
for (int i = 1; i <= N; ++i) siz[i] = 1;
Solve(1, M, 1, Q);
for (int i = 1; i <= Q; ++i) printf("%d\n", ans[i]);
return 0;
}


## E - Candy Piles

#include <cstdio>
#include <algorithm>

const int MN = 100005;

int N, A[MN];
int que[MN], l, r;

int main() {
scanf("%d", &N);
for (int i = 1; i <= N; ++i) scanf("%d", &A[i]);
std::sort(A + 1, A + N + 1);
l = 1, r = 0;
int lstc = 0;
for (int i = 2; i <= N; ++i) {
if (A[i] == A[i - 1]) lstc ^= 1;
else {
int c = ~(A[i] - A[i - 1]) & 1;
if (c != lstc) que[++r] = A[i - 1] - lstc + i;
lstc = 0;
}
while (l <= r && que[l] <= i) ++l;
}
puts(lstc ^ (A[N] & 1) ^ ((r - l) & 1) ? "First" : "Second");
return 0;
}


## F - Leftmost Ball

1. $p_{i - 1} < p_i$
2. $q_{i - 1} < q_i$
3. $p_i < q_i$

$\mathrm{f}[i][j]$ 表示目前 $0$ 剩下靠后的 $i$ 个，有颜色的点剩下靠后的 $j$ 列时的方案数。此时必须有 $j \ge i$。转移显然：

$\mathrm{f}[i][j] = \mathrm{f}[i - 1][j] + \binom{i + j \cdot (K - 1) - 1}{K - 2} \cdot \mathrm{f}[i][j - 1]$

#include <cstdio>

typedef long long LL;
const int Mod = 1000000007;
const int MN = 2005, MS = 4000005;

inline int qPow(int b, int e) {
int a = 1;
for (; e; e >>= 1, b = (LL)b * b % Mod)
if (e & 1) a = (LL)a * b % Mod;
return a;
}

int Fac[MS], iFac[MS];
inline void Init(int N) {
Fac[0] = 1;
for (int i = 1; i <= N; ++i) Fac[i] = (LL)Fac[i - 1] * i % Mod;
iFac[N] = qPow(Fac[N], Mod - 2);
for (int i = N; i >= 1; --i) iFac[i - 1] = (LL)iFac[i] * i % Mod;
}
inline int Binom(int N, int M) {
return (LL)Fac[N] * iFac[M] % Mod * iFac[N - M] % Mod;
}

int N, K;
int f[MN][MN];

int main() {
scanf("%d%d", &N, &K);
if (K == 1 || N == 1) return puts("1"), 0;
Init(N * K);
f[0][0] = 1;
for (int j = 1; j <= N; ++j) f[0][j] = (LL)f[0][j - 1] * Binom(j * (K - 1) - 1, K - 2) % Mod;
for (int i = 1; i <= N; ++i) {
f[i][i] = f[i - 1][i];
for (int j = i + 1; j <= N; ++j)
f[i][j] = (f[i - 1][j] + (LL)f[i][j - 1] * Binom(i + j * (K - 1) - 1, K - 2)) % Mod;
}
printf("%lld\n", (LL)f[N][N] * Fac[N] % Mod);
return 0;
}

posted @ 2020-06-07 05:03  粉兔  阅读(60)  评论(0编辑  收藏