cf895d D. String Mark 组合数+细节

乘法逆元可以先除不尽再乘

枚举相对于a,b串的第一个不同位置

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>

using namespace std;

char a[1000005];
char b[1000005];

long long mod=1e9+7;

long long fac[1000005];
long long afac[1000005];

long long cnt[35];

long long powd(long long a,long long b)
{
    long long ans=1;
    while(b>0)
    {
        if(b%2==1)
            ans=ans*a%mod;
        a=a*a%mod;
        b/=2;
    }
    return ans;
}

int main() {

    fac[0]=1;afac[0]=1;
    for(long long i=1;i<=1000000;i++)
        fac[i]=fac[i-1]*i%mod,afac[i]=powd(fac[i],mod-2);

    while(~scanf("%s",a))
    {
        memset(cnt,0,sizeof(cnt));

        scanf("%s",b);
        int len=strlen(a);
        int sta;

        for(int i=0;i<len;i++)
        {
            if(a[i]!=b[i])
            {
                sta=i;
                break;
            }
        }

        int tcnt[35];
        memset(tcnt,0,sizeof(tcnt));
        long long ans=0;
        for(int i=len-1;i>sta;i--)
        {
            int cur=a[i]-'a';
            long long num=0;
            tcnt[cur]++;
            long long bas=fac[len-1-i];
            for(int j=0;j<26;j++)
            {
                if(tcnt[j]!=0)
                    bas=(bas*afac[tcnt[j]])%mod;
            }
            for(int j=cur+1;j<26;j++) {
                if (tcnt[j] != 0) {
                    ans = (ans + bas * tcnt[j] % mod) % mod;
                }
            }
        }
        //cout<<ans<<endl;
        tcnt[a[sta]-'a']++;
        long long bas1=fac[len-1-sta];
        for(int i=0;i<26;i++)
        {
            if(tcnt[i]!=0)
                bas1=(bas1*afac[tcnt[i]])%mod;
        }
        for(int i=(a[sta]-'a')+1;i<(b[sta]-'a');i++)
        {
            if(tcnt[i]!=0)
                ans=(ans+bas1*tcnt[i]%mod)%mod;
        }
        //cout<<ans<<endl;
        if(tcnt[b[sta]-'a']!=0) {
            tcnt[b[sta]-'a']--;
            for (int i = sta + 1; i < len; i++) {
                int cur = b[i] - 'a';
                long long num=0;
                long long bas=fac[len-1-i];
                for(int j=0;j<26;j++)
                {
                    if(tcnt[j]!=0)
                        bas=bas*afac[tcnt[j]]%mod;
                }

                for(int j=0;j<cur;j++)
                {
                    if(tcnt[j]!=0)
                        ans=(ans+bas*tcnt[j])%mod;
                }
                if(tcnt[cur]==0)
                    break;
                tcnt[cur]--;
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/c_czl/article/details/87967872