HDU 5482(思路题目)

来源:互联网 发布:手机sdr软件 编辑:程序博客网 时间:2024/06/06 10:47

对于一个串来说我们粗略的看,它有多少个子串只和它各个位置的相等关系有关,所以我们没必要在乎字符集有多大,只需要枚举n的所有划分,处理出cnt[i][j][k]cnt[i][j][k]cnt[i][j][k]表示长度为iii的串有jjj个不同的字符且有kkk个子串的方案,每一次枚举的时候要么后面加一个已经出现过的字符,要么加一个新的字符。这样搜索状态总数只有BellnBell_nBelln个,对于n=10n=10n=10绰绰有余。

对于每次询问,只需要枚举一下这个串有多少个不同的字符,然后组合数统计即可。


#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define rep1(i,x,y) for(int i=x;i<=y;i++)typedef long long ll;typedef unsigned long long llu;const int base = 123;const int N = 110;const int mod = 1e9 + 7;int ans[N] ;llu  tem[N];ll a[11][11][N]={0};void cal(int n,int co){   int cnt = 0;   rep1(i,1,n) {      llu ha = 0;      rep1(j,i,n) ha = ha*base+ans[j]+'a',tem[cnt++]=ha;   }   sort(tem,tem+cnt);   cnt = unique(tem,tem+cnt)-tem;   a[n][co][cnt]++;}void dfs(int p,int c){   rep1(i, 1 , c){      ans[p] = i;      cal(p,max(i,c-1));      if(p < 10) dfs(p+1,max(i+1,c));   }}int n,m,k;ll c[N];void init(){   c[0]=1;   rep1(i,1,min(n,k)) c[i] = c[i-1]*(k-i+1)%mod;}int main(){   dfs(1 , 1);   int T;   scanf("%d",&T);   while(T--){      scanf("%d %d %d",&n,&m,&k);      init();      ll an = 0;      rep1(i,1,n){         an = (an + (ll)a[n][i][m]*c[i]%mod)%mod;      }      printf("%d\n",(int)an);   }   return 0;}

0 0
原创粉丝点击