• AtCoder Beginner Contest 171 AK!


    这一场好神奇!能AK了

    AB水题,

    C - One Quadrillion and One Dalmatians

    把一个数字转化为字母,规则为 ([1,26]) 对应 ([a,z]) , 27 对应 aa .....


    循环至 N = 0即可,转26进制

    int main() {
        cin.tie(nullptr)->sync_with_stdio(false);
        ll N; cin >> N;
        string s;
        for (; N--; N /= 26) s.push_back(char(97 + N % 26));
        reverse(s.begin(), s.end());
        cout << s;
    }
    

    D - Replacing

    给出 (n) 个数和 (q) 次操作,每次操作将 (n) 个数中 (b) 转为 (c) 计算每次操作后 (n) 个数的和。


    map 存出现的次数,每次操作 sum = sum + mp[b] * (c - b);

    const int N = 1e5 + 10;
    int a[N];
    map<int, int>mp;
    int main() {
        cin.tie(nullptr)->sync_with_stdio(false);
        int n; cin >> n;
        ll sum = 0;
        for (int i = 1; i <= n; ++i) cin >> a[i], sum += a[i], mp[a[i]] += 1;
        int q; cin >> q;
        while (q--) {
            int b, c;
            cin >> b >> c;
            sum = sum + mp[b] * (c - b);
            mp[c] += mp[b];
            mp[b] = 0;
            cout << sum << '
    ';
        }
    }
    

    E - Red Scarf

    给出 (n) 个数,计算每个数对其余 (n-1) 个数的异或值


    我是伞兵,没看清 N 的范围是 (2e5)​ 交了两罚 RE,才反应过来

    因为 (x ⊕ x = 0) ,所以直接先对所有值 (⊕) ,最后单独异或每一个值

    const int N = 2e5 + 10;
    int a[N], sum;
    int main() {
        cin.tie(nullptr)->sync_with_stdio(false);
        int n; cin >> n;
        for (int i = 1; i <= n; ++i) cin >> a[i], sum ^= a[i];
        for (int i = 1; i <= n; ++i) cout << (sum ^ a[i]) << " ";
    }
    

    F - Strivore

    在一个小写字母串 (s) 的任意位置插入一个小写字母 (k) 次后可能得到多少不同的字符串。


    很明显需要我们去推导公式,答案肯定和 (s)​ 长度有关,

    (s)​ 视为单一的字母串,答案即 (sumlimits_{i = 0}^n26^i imes C_i^n imes 25^{n - i})

    证明过程参考于 mrcrack

    涉及排列组合,怎么选取这一下,比较考验人。

    为了验证下面算法正确,还专门针对相应的数据,编写了检验代码,感兴趣的读者,可以阅读AC代码之后的内容。

    如下数据模拟如下

    2
    ab
     
    3851
     
    以下生成过程(aabb,aaab,abbb等不会重复生成)
     
     
    原始字符长度是2,还需插入2个字符,最后字符串总长度是2+2=2
    1.原始字符a占据新字符串串首的位置
    a( )( )( )
    剩下4个空位,原始字符的后1个字符还需占据1个位置,对应的选择数目是C(3,1)=3
    a(b)( )( )
    a( )(b)( )
    a( )( )(b)
    1.1以如下形式为例
    a(b)( )( )
    剩下的两个空位,可以插入字符,插入的字符都不能与前一个字符雷同,每个位置都有25种形式
    a(b)(不能是字母b)(不能是字母b)
    对应的组合数量25*25
    1.2以如下形式为例
    a( )(b)( )
    剩下的两个空位,可以插入字符,插入的字符都不能与前一个字符雷同,每个位置都有25种形式
    a(不能是字母a)(b)(不能是字母b)
    对应的组合数量25*25
    1.3以如下形式为例(注:abbb只在此时生成)
    a( )( )(b)
    剩下的两个空位,可以插入字符,插入的字符都不能与前一个字符雷同,每个位置都有25种形式
    a(不能是字母a)(不能是字母a)(b)
    对应的组合数量25*25
    总的组合数量25*25*3=25^2*C(3,1)=26^0*25^2*C(3,1)
    2.原始字符a占据新字符串第二个位置
    ( )a( )( )
    新字符串第二个位置之后只剩下2个空位,原始字符的后2个字符还需占据1个位置,对应的选择数目是C(2,1)=2
    ( )a(b)( )
    ( )a( )(b)
    2.1以如下形式为例
    ( )a(b)( )
    剩下的a前的1个空位,可以插入字符,插入的字符可以是任意字符,每个位置都有26种形式,
    剩下的b后的1个空位,可以插入字符,插入的字符可以是不能与b雷同,每个位置都有25种形式,
    (任意字符)a(b)(不能是字母b)
    对应的组合数量26*25
    2.2以如下形式为例(注:aabb只在此时生成)
    ( )a( )(b)
    剩下的a前的1个空位,可以插入字符,插入的字符可以是任意字符,每个位置都有26种形式,
    剩下的a后的1个空位,可以插入字符,插入的字符可以是不能与a雷同,每个位置都有25种形式,
    (任意字符)a(不能是字母a)(b)
    对应的组合数量26*25
    总的组合数量26*25*2=26*25*C(2,1)=26^1*25^1*C(2,1)
    3.原始字符a占据新字符串第三个位置
    ( )( )a( )
    新字符串第三个位置之后只剩下1个空位,原始字符的后1个字符还需占据1个位置,对应的选择数目是C(1,1)=1
    ( )( )a(b)
    3.1以如下形式为例(注:aaab只在此时生成)
    ( )( )a(b)
    剩下的a前的2个空位,可以插入字符,插入的字符可以是任意字符,每个位置都有26种形式,
    (任意字符)(任意字符)a(b)
    对应的组合数量26*26=26^2*C(1,1)=26^2*25^0*C(1,1)
    结合上述所有情况,对应的组合数量是26^0*25^2*C(3,1)+26^1*25^1*C(2,1)+26^2*25^0*C(1,1)=3851
    

    根据上述模拟过程,对应的算法如下:

    原字符串长度是m,需插入n个字符,在新的字串空间n+m中,

    1.先放入第一个原始字符,该原始字符前有i(0<=i<=n)个空位,每个空位均有26种摆法,对应,26^i.

    2.此时,总长度是n+m,已占据了i+1个字符,剩下n+m-(i+1)个空位,在剩下的空位中选择m-1个位置给原始字符串中剩下的m-1个字母使用,有C(n+m-i-1,m-1)种选择方式。

    3.此时还剩下n+m-(i+1)-(m-1)=n-i个空位,在这剩下每个空位对应着25种选法(26个字母,扣除自左向右,最靠近该位的原字串字母,故剩下25个可选字母)。

    综上所述,得到之前说的结论

    [sumlimits_{i = 0}^n26^i imes C_i^n imes 25^{n - i} ]

    写法一:

    const int N = 2e6 + 10, mod = 1e9 + 7;
    ll fac[N] = {1}, inv[N];
    ll qpow(ll a, ll b) {
        ll ans = 1;
        for (; b; b >>= 1, a = a * a % mod) if (b & 1) ans = ans * a % mod;
        return ans;
    }
    void init() {
        for (int i = 1; i < N; ++i) fac[i] = fac[i - 1] * i % mod;
        inv[N - 1] = qpow(fac[N - 1], mod - 2); // 由逆元
        for (int i = N - 2; i >= 0; --i) inv[i] = inv[i + 1] * (i + 1) % mod;
    }
    ll C(int n, int m) { return fac[n] * inv[m] % mod * inv[n - m] % mod;}
    int main() {
        cin.tie(nullptr)->sync_with_stdio(false);
        init();
        ll n, m; string s;
        cin >> n >> s;
        m = int(s.size());
        ll ans = 0;
        for (int i = 0; i <= n; ++i) {
            ans = (ans + qpow(26, i) * C(n + m - i - 1, m - 1) % mod * qpow(25, n - i) % mod) % mod;
        }
        cout << ans;
    }
    

    写法二:

    const int N = 2e6 + 10, mod = 1e9 + 7;
    ll f[N] = {1};
    ll qpow(ll a, ll b) {
        ll ans = 1;
        for (; b; b >>= 1, a = a * a % mod) if (b & 1) ans = ans * a % mod;
        return ans;
    }
    ll C(int n, int m) {return f[n] * qpow(f[m], mod - 2) % mod * qpow(f[n - m], mod - 2) % mod;}
    int main() {
        cin.tie(nullptr)->sync_with_stdio(false);
        for (int i = 1; i <= N; ++i) f[i] = f[i - 1] * i % mod;
        ll n, k; string s;
        cin >> k >> s;
        n = int(s.size());
        ll ans = 0;
        for (ll i = n; i <= n + k; ++i) {
            ll zh = qpow(26, n + k - i);
            zh = zh * C(i - 1, n - 1) % mod;
            zh = zh * qpow(25, i - n) % mod;
            ans = (ans + zh) % mod;
        }
        cout << ans;
    }
    

    The desire of his soul is the prophecy of his fate
    你灵魂的欲望,是你命运的先知。

  • 相关阅读:
    kubernetes进阶(一) kubectl工具使用详解
    二进制安装kubernetes(七) 部署知识点总结
    1024程序员节:这就是国内开发者的现状?
    php 伪协议
    浅谈 PHP 与手机 APP 开发(API 接口开发)
    比RBAC更好的权限认证方式(Auth类认证)
    PHP获得毫秒数
    2020年PHP面试题附答案(实战经验)
    分享几套2019年各大公司最新的PHP面试题,几斤几两一试便知
    PHP面试题2019年百度工程师面试题及答案解析
  • 原文地址:https://www.cnblogs.com/RioTian/p/15119483.html
Copyright © 2020-2023  润新知