AtCoder Grand Contest 023

A - Zero-Sum Ranges

Problem Statement
We have an integer sequence A, whose length is N.

Find the number of the non-empty contiguous subsequences of A whose sums are 0. Note that we are counting the ways to take out subsequences. That is, even if the contents of some two subsequences are the same, they are counted individually if they are taken from different positions.

Constraints
1≤N≤2×105
−109≤Ai≤109
All values in input are integers.

Input is given from Standard Input in the following format:
N
A1 A2 … AN

Output
Find the number of the non-empty contiguous subsequences of A whose sum is 0.

Sample Input 1
6
1 3 -4 2 2 -2

Sample Output 1
3
There are three contiguous subsequences whose sums are 0: (1,3,−4), (−4,2,2) and (2,−2).

Sample Input 2
7
1 -1 1 -1 1 -1 1

Sample Output 2
12
In this case, some subsequences that have the same contents but are taken from different positions are counted individually. For example, three occurrences of (1,−1) are counted.

Sample Input 3
5
1 -2 3 -4 5

Sample Output 3
0
There are no contiguous subsequences whose sums are 0.

题意

求和为0的连续子数组个数。

题解

map记录前缀和相同的个数即可。

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
int main() {
    int n;
    cin >> n;
    map<ll, ll> p;
    p[0] = 1;
    ll sum = 0;
    ll ans = 0;
    while (n--) {
        int temp;
        cin >> temp;
        sum += temp;
        ans += p[sum];
        p[sum]++;
    }
    cout << ans << "\n";
    return 0;
}

B - Find Symmetries

Problem Statement
Snuke has two boards, each divided into a grid with N rows and N columns. For both of these boards, the square at the i-th row from the top and the j-th column from the left is called Square (i,j).
There is a lowercase English letter written in each square on the first board. The letter written in Square (i,j) is Si,j. On the second board, nothing is written yet.
*First, choose two integers A and B ( 0≤A,B<N ).
*Write one letter in each square on the second board. Specifically, write the letter written in Square (i+A,j+B) on the first board into Square (i,j) on the second board. Here, the k-th row is also represented as the (N+k)-th row, and the k-th column is also represented as the (N+k)-th column.

After this operation, the second board is called a good board when, for every i and j ( 1≤i,j≤N ), the letter in Square (i,j) and the letter in Square (j,i) are equal.

Find the number of the ways to choose integers A and B ( 0≤A,B<N ) such that the second board is a good board.

Constraints
1≤N≤300
Si,j ( 1≤i,j≤N ) is a lowercase English letter.

Input
Input is given from Standard Input in the following format:
N
S1,1S1,2..S1,N
S2,1S2,2..S2,N
:
SN,1SN,2..SN,N

Output
Print the number of the ways to choose integers A and B ( 0≤A,B<N ) such that the second board is a good board.

Sample Input 1
Copy
2
ab
ca

Sample Output 1
2

The second board is a good board when (A,B)=(0,1) or (A,B)=(1,0), thus the answer is 2.

Sample Input 2
4
aaaa
aaaa
aaaa
aaaa
Sample Output 2
16
Every possible choice of A and B makes the second board good.

Sample Input 3
5
abcde
fghij
klmno
pqrst
uvwxy

Sample Output 3
0
No possible choice of A and B makes the second board good.

题意

求N*N方阵中以某个点为左上角重构后为对称方阵的个数。

题解

解法一

扩展成2N × 2N之后dp求边长不小于N的对称子方阵个数。
(PS: 其实直接取模即可,不用真正扩展)

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
int main() {
    int n;
    cin >> n;
    if (n == 1) {
        cout << "1\n";
        return 0;
    }
    vector<string> s(n*2);
    for (int i = 0; i < n; i++) {
        cin >> s[i];
        s[i] += s[i];
        s[i+n] = s[i];
    }
    vector<vector<int>> dp(n*2, vector<int>(n*2, 1));
    ll ans = 0;
    for (int i = 1; i < 2*n-1; i++) {
        for (int j = 1; j < 2*n-1; j++) {
            int cnt = 0;
            for (int k = 1; k <= min(i, j) && s[i][j-k] == s[i-k][j]; k++) {
                cnt++;
            }
            dp[i][j] = 1 + min(dp[i-1][j-1], cnt);
            if (dp[i][j] >= n) ans++;
        }
    }
    cout << ans << "\n";
    return 0;
}

解法二

TODO 参考官方题解

C Painting Machines

Problem Statement
There are N squares lining up in a row, numbered 1 through N from left to right. Initially, all squares are white. We also have N−1 painting machines, numbered 1 through N−1. When operated, Machine i paints Square i and i+1 black.

Snuke will operate these machines one by one. The order in which he operates them is represented by a permutation of (1,2,…,N−1), P, which means that the i-th operated machine is Machine Pi.

Here, the score of a permutation P is defined as the number of machines that are operated before all the squares are painted black for the first time, when the machines are operated in the order specified by P. Snuke has not decided what permutation P to use, but he is interested in the scores of possible permutations. Find the sum of the scores over all possible permutations for him. Since this can be extremely large, compute the sum modulo 109+7.

Constraints
2≤N≤1e6
Input
Input is given from Standard Input in the following format:
N

Output
Print the sum of the scores over all possible permutations, modulo 109+7.

Sample Input 1
4

Sample Output 1
16
There are six possible permutations as P. Among them, P=(1,3,2) and P=(3,1,2) have a score of 2, and the others have a score of 3. Thus, the answer is 2×2+3×4=16.

Sample Input 2
2

Sample Output 2
1
There is only one possible permutation: P=(1), which has a score of 1.

Sample Input 3
5

Sample Output 3
84

Sample Input 4
100000

Sample Output 4
341429644

题意

N×1 的格子, N-1 台机器,第i个机器能把i和i+1的方阵染黑。机器顺序有N!种,求每种中将所有格子染黑的操作数的和(即\(sum{k_i}, k_i是第i种顺序中最后一个染黑的操作数\) )。

题解

枚举k次操作后染黑的贡献,即经过k次操作后全部染黑的机器顺序数,然后求和即可。

令f[i]为至少k次操作之后全部染黑的顺序数量。显然k中至少有一次为染第一第二个格子,否则第一个无法变黑。此时剩下k-1种操作,需要把N-2个格子染黑,每个操作染黑的个数为1或者2。
可先全部减一,即k-1种操作,需要把N-2-(k-1)个格子染黑, 每个操作染黑的个数为0或者1。也就是组合C(k-1, n-1-k) k >= n/ 2能保证将格子全染黑。此外这K个操作时可以调换的, 这k个操作
之外的也是可以调换的,所以f[i]=C(k-1, n-1-k) * K! * (N-1-K)!。

注意f[i]算的是至少k种, 恰好为K种的个数应为f[i]-f[i-1], 算好组合数和阶乘然后枚举即可。

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int maxN = 1e6 + 5;
const int mod = 1e9 + 7;
ll frac[maxN];
ll inv[maxN];
ll f[maxN];
ll pw(ll a, ll b) {
    ll ans = 1;
    while (b) {
        if (b&1) ans = ans * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return ans;
}
void init() {
    frac[0]= 1;
    inv[0] = 1;
    for (int i = 1; i <= maxN; i++) {
        frac[i] = frac[i-1] * i % mod;
        inv[i] = pw(frac[i], mod-2);
    }
}
ll c(ll m, ll n) {
    if (m < n) return 0;
    if (n == 0) return 1;
    return frac[m] * inv[n] % mod * inv[m-n] % mod;
}
int main() {
    int n;
    cin >> n;
    init();
    f[2] = 1;
    ll ans = 0;
    for (ll i = n/2; i < n; i++) {
        f[i] = c(i-1, n-1-i) * frac[i] % mod * frac[n-1-i] % mod;
        //cout << f[i] << "\n";
        ans = (ans + (f[i] - f[i-1] + mod) % mod * i) % mod;
    }
    cout << ans << "\n";
    return 0;
}
posted @ 2018-05-07 00:09  hxidkd  阅读(279)  评论(0编辑  收藏  举报