AtCoder Beginner Contest 171(补题)

C - One Quadrillion and One Dalmatians

在这里插入图片描述
在这里插入图片描述

题意:

现在 1 到 26 1到26 126的数字为 a 到 z a到z az 27 27 27 702 702 702数字为 aa, ab, ac, …, zy, zz,475255,475256为aaaaa, aaaab,现在给你数字 n n n,让你输出对应的字符串

思路:

26个字母,所以转换为26进制,每次取余前,要减去1,把 [ 1 , 26 ] [1,26] [1,26]映射到 [ 0 , 25 ] [0,25] [0,25],然后输出即可

#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll n;
stack<int> sta;

int main() {
    cin >> n;
    while (n) {
        n--;
        sta.push(n % 26);
        n /= 26;
    }
    while (!sta.empty()) {
        int x = sta.top();
        sta.pop();
        printf("%c", x + 'a');
    }
    return 0;
}

F - Strivore

在这里插入图片描述
在这里插入图片描述

题意:

给一个长度为 m m m字符串,现在可以往字符串里加任意字符,可以加 n n n次,问最终会形成多少种字符串,答案对 1 0 9 + 7 10^9+7 109+7取模

思路:

组合数(排列组合)+去重+快速幂+逆元
n n n次字符,最终字符串长度是 n + m n+m n+m,现在先确定 s s s字符串的第一个字母的位置在 i i i号位置 ( 1 < = i < = n + 1 ) (1<=i<=n+1) (1<=i<=n+1),那么此时 i i i号位置前面的每个位置的字母情况都是26,所以就是 2 6 i − 1 26^{i-1} 26i1, i i i后面的位置,先从后面的位置选出 s s s串剩下 m − 1 m-1 m1个字母的位置,由于相对顺序是固定的,所以是 C n + m − i m − 1 C^{m-1}_{n+m-i} Cn+mim1然后每个 s s s 串字母后面不选相同的字母,用于去重,所以是 2 5 n + m − i − m + 1 25^{n+m-i-m+1} 25n+mim+1,即 2 5 n − i + 1 25^{n-i+1} 25ni+1种情况,
小证明: 若有个 s s s字符串为 a b c abc abc
那么枚举位置 i i i的时候,会有这种情况, _____a()()()()b______c
如果a的第二个位置填了a,就是_____aa()()()b______c
那么下次枚举第一个字母a位置的位置,为下一个位置 i + 1 i+1 i+1
也就是_____a()()()b______c
而此时这个a前面由于是26种情况
肯定会有_____aa()()()b______c
所以重复,这里枚举的是第二个位置,后面的位置同理如此
下面代码由于 i i i是从0开始循环到 n n n,所以公式有-1的差距
公式: ∑ i = 0 n \sum \limits_{i=0} ^{n} i=0n ⋅ 2 6 i ·26^{i} 26i ⋅ C n + m − i − 1 m − 1 ·C^{m-1}_{n+m-i-1} Cn+mi1m1 ⋅ 2 5 n − i ·25^{n-i} 25ni

#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;
const int N = 1e6 + 10;
#define ll long long
string s;
int n;
ll fact[N*2], infact[N*2];
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 % mod;
        k >>= 1;
    }
    return res;
}
void init() {
    fact[0] = infact[0] = 1;
    for (int i = 1; i < 2*N; i++) {
        fact[i] = (ll)fact[i - 1] * i % mod;
        infact[i] = (ll)infact[i - 1] * qmi(i, mod - 2, mod) % mod;
    }
}
ll C(int a, int b) { return fact[a] * infact[b] % mod * infact[a - b] % mod; }
int main() {
    init();
    cin >> n >> s;
    ll res = 0;
    int m = s.size();
    for (int i = 0; i <= n; i++) {
        res = (ll)res + qmi(26, i, mod) % mod * C(n + m - i - 1, m - 1) % mod *
                            qmi(25, n - i, mod) % mod;
    }
    cout << res % mod << endl;
}

To be continued
如果你有任何建议或者批评和补充,请留言指出,不胜感激

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值