Bnuoj--34985(DP,矩阵快速幂)
2014-10-09 00:32:18
思路:像这样的规律题一定要能想到DP,dp[i][j]表示长度为 i 的字串,从结尾开始往前数有 j 个不重复的元素,令该值为subnum。(当 j 达到 k + 1时显然字串非法)
对于长度为 i - 1,subnum为 j 的字串:在结尾加上一个元素可能使得subnum为1、2、3....j (想想为什么),也可能使得subnum为 j + 1 (要求所加元素与前 j 个不同)
于是问题来了,DP方程?答:dp[i][j] = ∑(k <= s <= j) dp[i - 1][s] + (k + 1 - (j - 1)) * dp[i - 1][j - 1] 。
1 /************************************************************************* 2 > File Name: 34985.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Wed 08 Oct 2014 09:47:28 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <map> 14 #include <set> 15 #include <queue> 16 #include <iostream> 17 #include <algorithm> 18 using namespace std; 19 #define lp (p << 1) 20 #define rp (p << 1|1) 21 #define getmid(l,r) (l + (r - l) / 2) 22 #define MP(a,b) make_pair(a,b) 23 typedef long long ll; 24 const int INF = 1 << 30; 25 const int RA = 10; 26 const int mod = 20140518; 27 28 int T,k; 29 ll n; 30 31 struct Mx{ 32 ll a[RA][RA]; 33 void clear(){ memset(a,0,sizeof(a));} 34 void stand(){ memset(a,0,sizeof(a));for(int i = 1; i <= k; ++i) a[i][i] = 1;} 35 Mx operator * (Mx b){ 36 Mx c; c.clear(); 37 for(int i = 1; i <= k; ++i) 38 for(int j = 1; j <= k; ++j) 39 for(int m = 1; m <= k; ++m){ 40 c.a[i][j] = (c.a[i][j] + a[i][m] * b.a[m][j]) % mod; 41 } 42 return c; 43 } 44 }; 45 46 Mx Mx_pow(){ 47 Mx res; res.stand(); 48 Mx t; t.clear(); 49 for(int i = 1; i <= k; ++i){ 50 for(int j = i; j <= k; ++j) t.a[i][j] = 1; 51 if(i > 1) t.a[i][i - 1] = k + 2 - i; 52 } 53 ll num = n - 1; 54 while(num){ 55 if(num & 1) res = res * t; 56 num >>= 1; 57 t = t * t; 58 } 59 return res; 60 } 61 62 int main(){ 63 scanf("%d",&T); 64 for(int Case = 1; Case <= T; ++Case){ 65 scanf("%lld%d",&n,&k); 66 Mx ans; ans.clear(); 67 ans.a[1][1] = k + 1; 68 ans = Mx_pow() * ans; 69 ll sum = 0; 70 for(int i = 1; i <= k; ++i) sum = (sum + ans.a[i][1]) % mod; 71 printf("Case #%d: %lld\n",Case,sum); 72 } 73 return 0; 74 }