其实总的感觉也不是很难
就是昨天看到第二题就放弃了
简单来说就是组合数学一点点+字典树一点点
像是一个数位dp
#include<bits/stdc++.h> #define re return #define inc(i,l,r) for(ll i=l;i<=r;++i) using namespace std; template<typename T>inline void rd(T&x) { char c;bool f=0; while((c=getchar())<'0'||c>'9')if(c=='-')f=1; x=c^48; while((c=getchar())>='0'&&c<='9')x=x*10+(c^48); if(f)x=-x; } #define ll long long ll n,k; const int maxn=1000005,mod=1e9+7; ll tot,tr[maxn][27],ed[maxn],cnt[maxn]; char s[maxn]; inline void insert() { ll len=strlen(s+1); ll rt=0; inc(i,1,len) { if(!tr[rt][s[i]-'a']) tr[rt][s[i]-'a']=++tot; rt=tr[rt][s[i]-'a']; } ed[rt]=1; ++cnt[rt]; } inline void dfs(ll rt) { if(ed[rt])re; inc(i,0,25) if(tr[rt][i]) { dfs(tr[rt][i]); cnt[rt]+=cnt[tr[rt][i]]; } } ll slen,st=1; ll jc[maxn],jcinv[maxn],ans,Ans,CNT; inline void find(ll rt) { if(ed[rt]) { Ans=(Ans+jc[n-CNT]*jcinv[n-k]%mod*ans%mod)%mod; cnt[rt]--; re ; } ll x=s[st]-'a'; inc(i,0,25) if(i<x) { if(tr[rt][i])ans+=cnt[tr[rt][i]]; //因为下标从0开始 } else { ++st; find(tr[rt][x]); cnt[rt]--; re ; } } inline void Get_jc() { jcinv[0]=jcinv[1]=jc[1]=jc[0]=1; inc(i,2,n) { jc[i]=jc[i-1]*i%mod; jcinv[i]=(mod-mod/i)*jcinv[mod%i]%mod; } inc(i,2,n)jcinv[i]=jcinv[i-1]*jcinv[i]%mod; } int main() { freopen("in.txt","r",stdin); rd(n),rd(k); inc(i,1,n) { scanf("%s",s+1); insert(); } dfs(0); Get_jc(); scanf("%s",s+1); while(CNT<k) { ++CNT; ans=0; find(0); } printf("%lld",(Ans+1)%mod); re 0; }