期望得分:40+80+30=150

实际得分:80+70+0=150

 

T1

LYK loves string(string)

Time Limit:1000ms   Memory Limit:128MB

 

题目描述

LYK喜欢字符串,它认为一个长度为n的字符串一定会有n*(n+1)/2个子串,但是这些子串是不一定全部都不同的,也就是说,不相同的子串可能没有那么多个。LYK认为,两个字符串不同当且仅当它们的长度不同或者某一位上的字符不同。LYK想知道,在字符集大小为k的情况下,有多少种长度为n的字符串,且该字符串共有m个不相同的子串。

由于答案可能很大,你只需输出答案对1e9+7取模后的结果即可。

 

输入格式(string.in)

一行3个数n,m,k。

 

输出格式(string.out)

    一行,表示方案总数。

 

输入样例

2 3 3

 

输出样例

6

 

样例解释

共有6种可能,分别是ab,ac,ba,bc,ca,cb。

 

数据范围

对于20%的数据:1<=n,k<=5。

对于40%的数据:1<=n<=5,1<=k<=1000000000。

对于60%的数据:1<=n<=8,1<=k<=1000000000。

对于100%的数据:1<=n<=10,1<=m<=100,1<=k<=1000000000。

 

Hint

本题非常easy。

 

k再大也没有用,最多就用n种字符,最后乘个组合数即可

搜索出用i(i<=n)种字符,有m种不同子串的字符串的个数 f[i]

ans= Σ f[i]*C(k,i)

 

搜索的时候每次只往后扩增一个新字母

即 若当前字母为i,下一个字母的范围为[1,i+1]

设字符集大小为S

这样对于搜出的每种方案 * S的阶乘 即为 用 S 种 字符的答案

 

判断一个字符串内有多少种不同的字串时,用哈希

 

#include<cstdio>
#include<algorithm>

using namespace std;

typedef long long LL;

const int mod=1e9+7;

int n,m;

int a[11];
LL has[11],b[11];

int f[11]; 

int inv[11];

LL Pow(LL a,int b)
{
    LL res=1;
    for(;b;a*=a,b>>=1)
        if(b&1) res*=a;
    return res;
}

void dfs(int now,int cnt,int lim)
{
    if(cnt>lim || n-now+1<lim-cnt) return;
    if(now==n+1)
    {
        for(int i=1;i<=n;++i) has[i]=has[i-1]*10+a[i];
        int sum=0;
        for(int len=1;len<=n;++len) 
        {
            for(int i=1;i+len-1<=n;++i) b[i]=has[i+len-1]-has[i-1]*Pow(10,len); 
            sort(b+1,b+n+1-len+1);
            for(int i=1;i+len-1<=n;++i) if(b[i]!=b[i-1]) sum++;
        }
        if(sum==m) f[lim]++;
        return;
    }
    for(int i=1;i<=cnt;++i) a[now]=i,dfs(now+1,cnt,lim);
    a[now]=cnt+1; dfs(now+1,cnt+1,lim);
}

int getC(int x,int y)
{
    int sum=1;
    for(int i=x-y+1;i<=x;++i) sum=1LL*sum*i%mod;
    for(int i=1;i<=y;++i) sum=1LL*sum*inv[i]%mod;
    return sum;
}

int pow(int a,int b)
{
    int res=1;
    for(;b;a=1LL*a*a%mod,b>>=1)
        if(b&1) res=1LL*res*a%mod;
    return res;
}

int main()
{
    freopen("string.in","r",stdin);
    freopen("string.out","w",stdout); 
    int k;
    scanf("%d%d%d",&n,&m,&k);
    int t=min(n,k);
    for(int i=1;i<=t;++i) dfs(1,0,i);
    LL bit=1;
    for(int i=1;i<=t;++i) 
    {
        inv[i]=pow(i,mod-2);
        bit*=i;
        f[i]=f[i]*bit%mod;
    }
    int ans=0;
    for(int i=1;i<=t;++i) ans=(ans+1LL*f[i]*getC(k,i)%mod)%mod;
    printf("%d",ans); 
}
View Code

相关文章: