DestinHistoire

 

CF895D String Mark(组合计数)

题目描述

  给出两个等长字符串 \(a,b(|a|,|b|\leq 10^6)\),保证字典序 \(a<b\)。求有多少个字符串 \(c\) 满足字典序 \(a<c<b\),其中 \(c\) 是 \(a\) 的一个全排列,答案对 \(10^9+7\) 取模。

分析

  设 \(solve(s)\) 为字典序小于串 \(s\) 的数目,则答案为 \(solve(b)-solve(a)-1\)。

  假设 \(a\) 串长度为 \(n\),则不同的全排列数为 \(\frac{n!}{cnt[1]!\times cnt[2]!\times \cdots\times cnt[26]!}\)(即多重集的全排列数)。

  类似数位dp的思想,按位考虑,假设要确定的 \(x\) 串的字典序小于 \(s\) 串。

  • 当前位置 \(i\) 填的字符小于 \(s[i]\),则后面 \(n-i\) 个字符可以任意填,方案数为 \(\frac{(n-i)!}{cnt[1]!\times cnt[2]!\times \cdots\times cnt[26]!}\)。

  • 当前位置 \(i\) 填的字符等于 \(s[i]\),则继续考虑第 \(i+1\) 位填的字符,相当于一个子问题。

  因此可以枚举第 \(i\) 位填的字符 \(j(j\in [1,s[i]-1])\),每枚举一个字符,答案就加上 \(\frac{(n-i)!cnt[j]}{cnt[1]!\times cnt[2]!\times \cdots\times cnt[26]!}\),枚举结束后 \(cnt[s[i]]\) 要 \(-1\),代表把第 \(i\) 位填上了字符 \(s[i]\),继续枚举第 \(i+1\) 位,\(\cdots\),依此递推即可。

代码

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
const int mod=1e9+7;
char a[N],b[N];
long long quick_pow(long long a,long long b)
{
    long long ans=1;
    while(b)
    {
        if(b&1)
            ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}
long long fac[N+10],inv[N+10];
void init()
{
    fac[0]=inv[0]=1;
    for(int i=1;i<=N;i++)
        fac[i]=fac[i-1]*i%mod;
    inv[N]=quick_pow(fac[N],mod-2);
    for(int i=N-1;i>=1;i--)
        inv[i]=inv[i+1]*(i+1)%mod;
}
int n,cnt[30];
long long solve(char *str)
{
    for(int i=1;i<=26;i++)
        cnt[i]=0;
    long long ans=0;
    for(int i=1;i<=n;i++)
        cnt[a[i]-'a'+1]++;
    for(int i=1;i<=n;i++)
    {
        int ch=str[i]-'a'+1;
        long long temp=fac[n-i];
        for(int j=1;j<=26;j++)
            temp=temp*inv[cnt[j]]%mod;
        for(int j=1;j<=ch-1;j++)
            if(cnt[j]>=1)
                ans=(ans+temp*cnt[j]%mod)%mod;
        if(cnt[ch]==0)
            break;
        cnt[ch]--;
    }
    return ans;
}
int main()
{
    init();
    scanf("%s%s",a+1,b+1);
    n=strlen(a+1);
    cout<<(solve(b)-solve(a)-1+mod)%mod<<endl;
    return 0;
}

posted on 2020-11-03 21:52  DestinHistoire  阅读(129)  评论(0)    收藏  举报

导航