Vijos P1067Warcraft III 守望者的烦恼

题目

背景

守望者-warden,长期在暗夜精灵的的首都艾萨琳内担任视察监狱的任务,监狱是成长条行的,守望者warden拥有一个技能名叫“闪烁”,这个技能可以把她传送到后面的监狱内查看,她比较懒,一般不查看完所有的监狱,只是从入口进入,然后再从出口出来就算完成任务了。

描述

头脑并不发达的warden最近在思考一个问题,她的闪烁技能是可以升级的,k级的闪烁技能最多可以向前移动k个监狱,一共有n个监狱要视察,她从入口进去,一路上有n个监狱,而且不会往回走,当然她并不用每个监狱都视察,但是她最后一定要到第n个监狱里去,因为监狱的出口在那里,但是她并不一定要到第1个监狱。

守望者warden现在想知道,她在拥有k级闪烁技能时视察n个监狱一共有多少种方案?

格式

输入格式

第一行是闪烁技能的等级k(1<=k<=10)
第二行是监狱的个数n(1<=n<=2^31-1)

输出格式

由于方案个数会很多,所以输出它 mod 7777777后的结果就行了

样例1

样例输入1[复制]

 
2
4

样例输出1[复制]

 
5

限制

各个测试点1s

提示

把监狱编号1 2 3 4,闪烁技能为2级,
一共有5种方案
→1→2→3→4
→2→3→4
→2→4
→1→3→4
→1→2→4

小提示:建议用int64,否则可能会溢出

 

题解

这道题目是矩阵,我竟然有点忘记矩阵乘法了QAQ赶快再做几题!

代码

 1 /*Author:WNJXYK*/
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 
 6 const int M=7777777;
 7 int n,siz; 
 8 long long mul[11][11],ans[11];
 9 inline void mTimes(long long a[],long long b[][11]){
10     long long c[11];
11     memset(c,0,sizeof(c));
12     for (int i=1;i<=siz;i++){
13         for (int j=1;j<=siz;j++){
14             c[i]=(c[i]+a[j]*b[i][j])%M;
15         }
16     }
17     memcpy(a,c,sizeof(c));
18 }
19 inline void mTimes(long long a[][11],long long b[][11]){
20     long long d[11][11];
21     memset(d,0,sizeof(d));
22     for (int i=1;i<=siz;i++){
23         for (int j=1;j<=siz;j++){
24             for (int k=1;k<=siz;k++){
25                 d[i][j]=(d[i][j]+a[i][k]*b[k][j])%M;
26             }
27         }
28     }
29     memcpy(a,d,sizeof(d));
30 }
31 
32 int main(){
33     scanf("%d%d",&siz,&n);
34     ans[0]=1;
35     for (int i=1;i<=siz;i++){
36         for (int j=0;j<i;j++){
37             ans[i]+=ans[j];
38         }
39     }
40     for (int i=1;i<=siz;i++)mul[siz][i]=1;
41     for (int i=2;i<=siz;i++)mul[i-1][i]=1;
42     n--;
43     while(n){
44         if (n&1) mTimes(ans,mul);
45         n/=2;
46         mTimes(mul,mul);
47     }
48     printf("%lld\n",ans[1]);
49     return 0;
50 }
View Code

 

posted @ 2014-11-03 11:29  WNJXYK  阅读(305)  评论(0编辑  收藏  举报

WNJXYK-我今年一定要努力!