AGC002 do question a small note

E. Candy Piles

The meaning of problems

n candy stack, the i-th stack has a [i] candy. Game two, each can finish taking the biggest bunch of candy, or take away from all of a heap of candy, candy taken away the last one to lose. When asked who are taking the optimal strategy winner yes.

n ≤ 100000, a[i] ≤ 1e9

answer

Very wonderful solution.

Press a [i] in descending row number order. Icon shown in the coordinate system, where x = i is the position having a height of a [i] column.

Can be found, took the biggest pile, is a unit right away; take a heap from all, it is to take up one unit. From (0, 0) start walking.

Playing table can be found in the same point as the slope of a straight line on the outcome of a state, and a point on the border, right up there a number of steps that can take is odd win state.

UPD: In addition to the termination state, the state of the outcome of all points on the slope of the straight line 1 is the same. Therefore, the state of a point in the same point can be pushed directly to the state and outcome of a border. To prove this conclusion proved in two ways. 1, if a point is to win state, its upper right corner point can not be doomed to failure state, otherwise next opponents will be able to come to a point to make ourselves into the upper right corner will defeated state; 2, point if a state is doomed to failure, its upper right corner point must win state. The set point is the coordinates (0, 0), (0, 1) and (1, 0) are win state, the conclusion is that a (2, 1) and (1, 2) must win state to (1, 1) can only be transferred to the winning state, which itself is doomed to failure state.

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
 
int n, a[N];
 
int main() {
    cin >> n;
    for (int i = 1; i <= n; ++i)
        cin >> a[i];
    sort(a + 1, a + n + 1);
    reverse(a + 1, a + n + 1);
    int tmp = 1, r = tmp;
    while (tmp < n && a[tmp + 1] >= tmp + 1)
        ++tmp;
    while (a[r + 1] >= tmp) ++r;
    int ans = ((a[tmp] - tmp) & 1) || ((r - tmp) & 1);
    puts(ans ? "First" : "Second");
    return 0;
}

F. Leftmost Ball

The meaning of problems

There are n color balls, each with k. These n * k balls in a row, the leftmost balls and all the colors painted the n + 1 color. Q. How many final sequence of colors possible.

n, k ≤ 2000

answer

Let's assume that in the final sequence, the order (that is, the color of the second ball) the first occurrence of each color is 1, 2, ..., n, the final answer multiplied by n! Can be.

Consider dp. Order dp [i] [j] i is put colors, and determines the 1, 2, ..., j + number of programs becomes a position of the ball appears one color is n.

If the next ball to put the first ball of a certain color, dp [i] [j + 1] + = dp [i] [j]

If the next ball of the second ball discharge a certain color, then the color you want the remaining (k - 2) is inserted into the remaining balls ((n - i) * k - (j - i) - 1) a position, i.e. dp [i + 1] [j] + = dp [i] [j] * C ((n - i) * k - (j - i) - 1, k - 2)

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int N = 2005;
const int mod = 1e9 + 7;
 
int n, k;
LL f[N][N], fac[N * N], inv[N * N], fav[N * N];
 
inline void Add(LL &x, LL y) {
    x += y;
    if (x >= mod) x -= mod;
}
 
inline LL C(LL x, LL y) {
    if (x < 0 || x < y) return 0;
    return (fac[x] * fav[y] % mod * fav[x - y] % mod);
}
 
int main() {
    cin >> n >> k;
    if (k == 1) return 0 * puts("1");
    fac[0] = fav[0] = 1;
    fac[1] = fav[1] = inv[1] = 1;
    for (int i = 2; i < N * N; ++i) {
        inv[i] = (-mod / i * inv[mod % i] % mod) + mod;
        fac[i] = fac[i - 1] * i % mod;
        fav[i] = fav[i - 1] * inv[i] % mod;
    }
    f[0][0] = 1;
    for (int i = 0; i <= n; ++i) {
        for (int j = i; j <= n; ++j) {
            if (j < n) {
                Add(f[i][j + 1], f[i][j]);
            }
            if (i < j) {
                if ((n - i) * k - j + i - 1 >= 0)
                    Add(f[i + 1][j], f[i][j] * C((n - i) * k - j + i - 1, k - 2) % mod);
            }
        }
    }
    for (int i = 1; i <= n; ++i) {
        f[n][n] = f[n][n] * i % mod;
    }
    cout << f[n][n] << endl;
    return 0;
}

Guess you like

Origin www.cnblogs.com/Vexoben/p/11729266.html