背景
守望者-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,否则可能会溢出
来源
杜杜我爱你个人原创
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <stdlib.h> 5 #include <math.h> 6 7 using namespace std; 8 const int maxn=20,mod=7777777; 9 long long int f[maxn];//存放到第几个监狱时的走法 10 11 struct mat{ 12 long long int a[maxn][maxn]; 13 }res,ans; 14 15 //matrix multiply j1*j2 n dimension(square) 16 mat cheng1(mat j1,mat j2,int n){ 17 mat tmp; 18 for(int i=1;i<=n;i++) 19 for(int j=1;j<=n;j++) 20 tmp.a[i][j]=0; 21 for(int i=1;i<=n;i++) 22 for(int j=1;j<=n;j++) 23 for(int k=1;k<=n;k++) 24 tmp.a[i][j]=(j1.a[i][k]*j2.a[k][j])%mod+tmp.a[i][j]; 25 return tmp; 26 } 27 28 29 //quickpow k dimension n multi_n 30 mat qp(int k,int n){ 31 for(int i=1;i<=k;i++) 32 for(int j=1;j<=k;j++){ 33 if(i==j)ans.a[i][j]=1; 34 else ans.a[i][j]=0; 35 } 36 while(n){ 37 if(n&1) 38 ans=cheng1(res,ans,k); 39 res=cheng1(res,res,k); 40 n>>=1; 41 } 42 return ans; 43 } 44 45 int main() 46 { 47 int k,n;//k级 n个 48 scanf("%d%d",&k,&n); 49 f[0]=1; 50 for(int i=1;i<=k;i++){ 51 f[i]=0; 52 for(int j=i-1;j>=0&&j>=i-k;j--){ 53 f[i]+=f[j]; 54 } 55 } 56 for(int i=1;i<=k-1;i++){ 57 res.a[i][i+1]=1; 58 res.a[k][i]=1; 59 } 60 res.a[k][k]=1; 61 res=qp(k,n-k); 62 long long int m[maxn]={0}; 63 for(int j=1;j<=k;j++){ 64 m[k]+=res.a[k][j]*f[j]; 65 } 66 printf("%lld ",m[k]%mod); 67 return 0; 68 }
大概是矩阵快速幂优化dp的经典题型,学习了
状态转移方程非常好想,所以一开始天真的我想用滚动数组把它全部循环一遍
然而数据太大了……当然是没法过的
所以要用矩阵乘法来缩短时间,算法了解一下->点这里
然后就是那个mod777...7……这句话我看了很久才明白是啥意思……
不过改完还是wa了几次,40分,原因是我只是在结果那边简单地%了一下mod(这有个毛用啊)
其实中间计算的时候数据就已经溢出了
所以又改了一下矩阵乘法计算过程中的数,因为反正都相当于是减了很多个mod所以对最后结果没有什么影响