【2018 计蒜之道 复赛】计蒜客 贝壳找房计数比赛

固定字符串 t t 不动,对 s s 中剩下的字母求有重复元素的排列问题,最后再考虑 t t 在整个串中的位置。

#include
#include
#define LL long long
const int p=1000000007;
char s[100010],t[100010];
int cnt[30],a[30],fac[100010],inv[100010],l,m,n,tot,ans;
int pow(int a,int x)
{
    int ret=1;
    for (;x;x>>=1,a=(LL)a*a%p)
        if (x&1) ret=(LL)ret*a%p;
    return ret;
}
int c(int n,int m)
{
    return (LL)fac[n]*inv[m]%p*inv[n-m]%p;
}
void solve()
{
    scanf("%s%s",s+1,t+1);
    l=strlen(s+1);
    m=strlen(t+1);
    memset(cnt,0,sizeof(cnt));
    for (int i=1;i<=l;i++) cnt[s[i]-'a'+1]++;
    for (int i=1;i<=m;i++) cnt[t[i]-'a'+1]--;
    n=tot=0;
    for (int i=1;i<=26;i++)
        if (cnt[i]<0)
        {
            printf("0\n");
            return;
        }
        else if (cnt[i])
        {
            a[++n]=cnt[i];
            tot+=cnt[i];
        }
    ans=tot+1;
    for (int i=1;i<=n;i++)
    {
        ans=((LL)ans*c(tot,a[i]))%p;
        tot-=a[i];
    }
    printf("%d\n",ans);
}
int main()
{
    fac[0]=1;
    for (int i=1;i<=100000;i++) fac[i]=(LL)fac[i-1]*i%p;
    for (int i=0;i<=100000;i++) inv[i]=pow(fac[i],p-2);
    int T;
    scanf("%d",&T);
    while (T--) solve();
}

你可能感兴趣的:(数学,其他oj)