AtCoder Beginner Contest 154

AtCoder Beginner Contest 154

https://atcoder.jp/contests/abc154
今天也比较简单。

E - Almost Everywhere Zero

贪心或者数位dp。
(其实我这个贪心应该就是在模拟数位dp)

贪心

#include <bits/stdc++.h>
#define ll long long

using namespace std;
string s;
int k, n;
ll sum = 0;

int main () {
    cin >> s >> k;
    n = s.size ();
    if (k == 1) {
        sum = 9ll * (n - 1) + (s[0] - '0');
    }
    else if (k == 2) {
        sum = max(0ll, 81ll * (n - 2) * (n - 1) / 2);
        sum += 9ll * (s[0] - '0' - 1) * (n - 1);
        //3...
        //cout << sum << ' ';
        bool find = false;
        for (int i = 1; i < n; i++) {
            if (s[i] != '0') {
                find = true;
                sum += max(0ll, 9ll * (n - i - 1)) + (s[i] - '0');
                break;
            }
        }
        //if (!find)      sum += 9ll * (s[0] - '0') * (n - 1);
        if (n == 1)     sum = 0;
    }
    else { // k == 3
        for (int i = 2; i <= n - 2; i++)    sum += 729ll * i * (i - 1) / 2;
        sum += max(0ll, 81ll * (s[0] - '0' - 1) * (n - 1) * (n - 2) / 2);
        for (int i = 1; i < n; i++) {
            if (s[i] != '0') {
                sum += max(0ll, 81ll * (n - i - 1) * (n - i - 2) / 2) + max(0ll, 9ll * (s[i] - '0' - 1) * (n - i - 1));
                for (int j = i + 1; j < n; j++) {
                    if (s[j] != '0') {
                        sum += max (0ll, 9ll * (n - j - 1)) + max (0, s[j] - '0');
                        break;
                    }
                }
                break;
            }
        }
        if (n < 3)  sum = 0;
    }
    cout << sum;
}

数位dp

#include <bits/stdc++.h>
#define ll long long

using namespace std;
const int N = 105;
ll K, n, a[N], f[N][2][10]; //f[i][j][k]:最高i位,0/1达到上界与否,非0整数的个数
string s;

int main() {
    cin >> s >> K;
    n = s.size();
    s = ' ' + s;
    for (int i = 1; i <= n; i++)    a[i] = s[i] - '0';

    f[0][1][0] = 1;                      
    for (int i = 0; i < n; i++) { //1-n的前一位
        for (int j = 0; j <= 1; j++) { //是否达到上限
            for (int k = 0; k <= K; k++) { //非0整数的个数
                for (int l = 0; l <= 9; l++) { //第i位的整数
                    if (j == 1 && l > a[i + 1])     break; //比上限大
                    if (k == K && l > 0)    break; //非0整数已放完k个且当前为不为0,则不用再放下去
                    ll kk = k + (bool)l, jj = (j == 1 && a[i + 1] == l);
                    f[i + 1][jj][kk] += f[i][j][k];
                }
            }
        }
    }
    cout << f[n][0][K] + f[n][1][K];
}

F - Many Many Paths

利用了组合数的一个小公式:

转化为前缀和相减的形式即可求出:

#include <bits/stdc++.h>
#define ll long long

using namespace std;
const int N = 2e6 + 5, mod = 1e9 + 7;
ll r1, r2, c1, c2;

ll fact[N], infact[N];

ll qmi(ll a, ll k, ll p){
    ll res = 1;
    while(k){
        if(k & 1)
            res = (ll)res * a % p;
        a = (ll)a * a % p;
        k >>= 1;
    }
    return res;
}

ll C (int a, int b) {
    if (a < b)  return 0;
    return fact[a] * infact[b] % mod * infact[a - b] % mod;
}

void init () {
    fact[0] = infact[0] = 1;
    for(int i = 1; i < N; i++){
        fact[i] = (ll)fact[i-1] * i % mod;
        infact[i] = (ll)infact[i-1] * qmi(i, mod - 2,mod) % mod;
    }
}

int main() {
    init ();
    cin >> r1 >> c1 >> r2 >> c2;
    ll sum = 0;
    for (int i = r1; i <= r2; i++) {
        (sum += C (i + c2 + 1, i + 1) - C(i + c1, i + 1) + mod) %= mod;
    }

    cout << sum;
}

//求\sum_{i=r1}^r2 \sum_{j=c1}^c2(C_{i+j}^i))
posted @ 2023-04-03 14:27  Sakana~  阅读(12)  评论(0编辑  收藏  举报