AtCoder Beginner Contest 042 题解

比赛链接:https://atcoder.jp/contests/abc042

A - Iroha and Haiku (ABC Edition)

题目大意:
给你三个数,判断能否组成一个 \(5,7,5\) 的排列。

示例程序:

#include <bits/stdc++.h>
using namespace std;
int a[3], b[] = {5, 5, 7};
int main()
{
    for (int i = 0; i < 3; i ++) cin >> a[i];
    sort(a, a+3);
    for (int i = 0; i < 3; i ++) {
        if (a[i] != b[i]) {
            puts("NO");
            return 0;
        }
    }
    puts("YES");
    return 0;
}

B - Iroha Loves Strings (ABC Edition)

题目大意:
\(N\) 个长度为 \(L\) 的字符串拼起来,要求拼起来之后的字符串字典序最小。

解题思路:
一开始想到的思路是字典树,但是因为这道题目数据量比较小,所以开 string 数组排一下序就可以了。

示例程序:

#include <bits/stdc++.h>
using namespace std;
string s[110];
int n, L;
int main() {
    cin >> n >> L;
    for (int i = 0; i < n; i ++) cin >> s[i];
    sort(s, s+n);
    for (int i = 0; i < n; i ++) cout << s[i];
    return 0;
}

C - Iroha's Obsession

题目大意:
找一个大于等于 \(n\) 的最小数字,要求这个数字的每一位都不能包含特定的一些数字。

解题思路:
首先 \(n\) 不会超过 \(9999\),能够证明答案最大不超过 \(99999\),所以可以从 \(n\) 开始暴力枚举,找到第一个满足条件的数字即可。

示例程序:

#include <bits/stdc++.h>
using namespace std;
int n, K, d;
bool no[10];
bool check(int n) {
    while (n) {
        if (no[n%10]) return false;
        n /= 10;
    }
    return true;
}
int main() {
    cin >> n >> K;
    while (K --) {
        cin >> d;
        no[d] = true;
    }
    while (!check(n)) n ++;
    cout << n << endl;
    return 0;
}

D - Iroha and a Grid

题目大意:
一个 \(H \times W\) 的二维格子,从左上角走到右下角,每次只能往右或往下走一个,且左下角的 \(A \times B\) 个格子不能走,求有多少种不同的方案?

解题思路:
一开始看成数据规模是100,后来才发现是10万,所以递推不行,得用数学方法

我们用 \(C_n^m\) 表示从 \(n\) 个数中选择 \(m\) 个数的组合数,则若不考虑左下方的 \(A \times B\) 个格子,则总方案数为 \(C_{H+W-2}^{H-1}\)

当然还要考虑所有不合法的方案数,所有不合法的方案数必然经过 \((H-A+1,B)\)\((H-A+2,B), \ldots, (H,B)\) 中的其中一个格子。

我们可以得到从 \((1,1)\) 走到 \((H-a+i,B)\) 然后下一步往右走,然后走到终点的方案数为 \(C_{H-A+i+B-2}^{B-1} \times C_{A-i+W-B-1}^{A-i}\)

所以总的方案数为

\[C_{H+W-2}^{H-1} - \sum\limits_{i=1}^{A} C_{H-A+i+B-2}^{B-1} \cdot C_{A-i+W-B-1}^{A-i} \]

示例代码:

#include <bits/stdc++.h>
using namespace std;
const long long MOD = 1000000007LL;
typedef long long ll;
void gcd(ll a , ll b , ll &d , ll &x , ll &y) {
    if(!b) {d = a; x = 1; y = 0;}
    else { gcd(b , a%b,d,y , x); y -= x * (a/b); }
}
ll inv(ll a , ll n) {
    ll d , x , y;
    gcd(a , n , d,  x , y);
    return d == 1 ? (x+n)%n : -1;
}
const int maxn = 200010;
ll fac[maxn];
void init() {
    fac[0] = 1;
    for (int i = 1; i < maxn; i ++) fac[i] = fac[i-1] * i % MOD;
}
ll C(int n, int m) {
    return fac[n] * inv(fac[m], MOD) % MOD * inv(fac[n-m], MOD) % MOD;
}
int H, W, A, B;
int main() {
    init();
    cin >> H >> W >> A >> B;
    ll sum = C(H+W-2, H-1);
    for (int i = 1; i <= A; i ++)
        sum = ( sum - C(H-A+i+B-2, B-1) * C(A-i+W-B-1, A-i) % MOD + MOD ) % MOD;
    cout << sum << endl;
    return 0;
}
posted @ 2021-03-02 14:04  quanjun  阅读(95)  评论(0编辑  收藏  举报