HackerRank Counting Perfect Subsequences 扩展欧几里得+组合数

本文参考自: 原文地址

We call a string, , consisting of the letters in the set  a perfect stringif both the conditions below are true:

where  denotes the number of occurrences of character  in . For example, the diagram below demonstrates why  is a perfect string:

image

Solve  queries, where each query consists of a string, . For each query, print the number of non-empty subsequences of  that are perfect strings. As this number can be very large, print it modulo .

Input Format

The first line contains an integer, , denoting the number of queries. 
Each of the  subsequent lines contains string  for a query.

Constraints

  • String  consists only of the following characters: abc, and d.

Subtask

  • For  of the total score, .

Output Format

For each , print the number of non-empty subsequences of  that are perfect strings, modulo , on a new line.

Sample Input 0

3
abcd
cad
dcc

Sample Output 0

3
1
2

Explanation 0

We peform the following  queries:

  1.  has  non-empty perfect subsequences: , and . Thus, the answer is .
  2.  has  non-empty perfect subsequence: . Thus, the answer is .
  3.  has  non-empty perfect subsequences:  and . Note that, while both these strings contain the same characters, they are distinct subsequences of (i.e.,  and ). Thus, the answer is .
无甚可说的,要算很大的组合数,用扩展欧几里得求组合数取模。
#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;

const long long mod=1e9+7;

int q;
char str[500010];

long long exgcd(long long a,long long b,long long &x,long long &y)
{
    if (a==0 && b==0) return -1;
    if (b==0)
    {
        x=1; y=0;
        return a;
    }
    long long d=exgcd(b,a%b,y,x);
    y-=a/b*x;
    return d;
}

long long mod_reverse(long long a,long long n)
{
    long long x; long long y;
    long long d=exgcd(a,n,x,y);
    if (d==1)
        return (x%n+n)%n;
    else return -1;
}

int main()
{
    gets(str);
    q=0;
    int len=strlen(str);
    for (int i=0; i<len; i++)
    {
        q=q*10+str[i]-'0';
    }
    while (q--)
    {
        gets(str);
        int len=strlen(str);
        long long a=0,b=0,c=0,d=0;
        for (int i=0; i<len ;i++)
        {
            if (str[i]=='a') a++;
            else if (str[i]=='b') b++;
            else if (str[i]=='c') c++;
            else if (str[i]=='d') d++;
        }
        long long p=min(a,b);
        long long q=min(c,d);
        long long tmpa=1;long long tmpb=1;
        long long ans1=1;
        for (long long i=1; i<=p; i++)
        {
            //cout<<"i="<<i<<endl;
            long long nn=mod_reverse(i,mod);
            tmpa=( (tmpa*(a-i+1))%mod )*nn%mod;
            tmpb=( (tmpb*(b-i+1))%mod )*nn%mod;
            ans1=(ans1+ (tmpa*tmpb)%mod ) % mod;
            //cout<<"ans1="<<ans1<<endl;
        }
        long long tmpc=1; long long tmpd=1;
        long long ans2=1;
        for (long long i=1; i<=q; i++)
        {
            //cout<<"i="<<i<<endl;
            long long nn=mod_reverse(i,mod);
            tmpc=( (tmpc*(c-i+1))%mod )*nn%mod;
            tmpd=( (tmpd*(d-i+1))%mod )*nn%mod;
            //cout<<"tmpc="<<tmpc<<" tmpd="<<tmpd<<endl;
            ans2=(ans2+ (tmpc*tmpd)%mod ) % mod;
            //cout<<"ans2="<<ans2<<endl;
        }
        long long ans=(ans1*ans2)%mod;
        ans=(ans-1+mod)%mod;
        cout<<ans<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39706019/article/details/81559115