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 }

 

posted @ 2014-10-09 00:42  Naturain  阅读(317)  评论(0编辑  收藏  举报