P1246

编码

这个东西可以看作组合的编号。然后一切都好搞了。

显然小于串长度的组合都符合。

接着等于串长度的组合我们逐位计数。

于是就有:

$$Ans=\sum_{i=1}^{n-1}C_{26}^i+\sum_{i=1}^n\sum_{j=s[i-1]-‘a’+1}^{s[i]-‘a’-1}C_{25-j}^{n-i}$$

输出就完了。

一开始想过直接暴力预处理出编号的方法,其实很可做,因为用 map 的话很容易出奇迹。

这个时间复杂度是 $O(n\cdot siz[a\cdots z])$ 的。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;

ll n,ans,flg;

ll f[30][30];

char s[10];

void init() {
f[0][0]=1;
for(ll i=1;i<=26;i++) {
for(ll j=0;j<=i;j++) {
f[i][j]=f[i-1][j]+f[i-1][j-1];
}
}
}

void write(ll x) {
static char buf[22];static ll len=-1;
if(x>=0) {
do{buf[++len]=x%10+48;x/=10;}while(x);
}
else {
putchar('-');
do{buf[++len]=-(x%10)+48;x/=10;}while(x);
}
while(len>=0) putchar(buf[len--]);
}

int main() {

init();

scanf("%s",s+1);s[0]='a'-1;
n=strlen(s)-1;

for(ll i=1;i<n;i++) {
if(s[i]>=s[i+1]) {
flg=1;break;
}
}

if(flg) {
write(0);
}
else {
for(ll i=1;i<n;i++) {
ans+=f[26][i];
}
for(ll i=1;i<=n;i++) {
for(ll j=s[i-1]-'a'+1;j<=s[i]-'a'-1;j++) {
ans+=f[25-j][n-i];
}
}
write(ans+1);
}

return 0;
}