题目描述
Fy 觉得自己玩 cf,lol 这种高端游戏已经够厉害了,于 是他决定去玩 dota2.结果 fy 的鼠标右键坏了,所以他就等 到 2250 买了把闪烁匕首,用跳刀前进,准备去送泉水。但 是 fy 一次最多前进 k 的距离,泉水离 fy 现在的距离是 n。 Fy 想知道他到泉水的方案数。
输入输出格式
输入格式:
第一行 2 个整数:k,n
输出格式:
一行 1 个整数:代表答案对 7777777 取膜的结果
数据范围约定
对于 30%的数据:n<=1000,k<=10
对于 100%的数据:1<=n<=2^31-1,1<=k<=10
题解
更具题目我们先来推一下,我们发现当允许的跳跃距离为 k 时,调到 i 新增加的方案数只会从(i-k)~ (i - 1)提供贡献,而其他的方案都可以归类到其中,所以我们就可以得到下面这个递推公式
初始量是f[1] = 1, f[0] = 1;
而由于数据范围是到2^31所以我们要考虑用矩阵乘法来优化递推:
代码
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define LL long long 4 5 struct Martix 6 { 7 LL a[12][12]; 8 Martix friend operator * (Martix x, Martix y) 9 { 10 Martix ans; 11 memset(ans.a, 0, sizeof(ans)); 12 for(int i = 1; i <= 11; ++ i) 13 for(int j = 1; j <= 11; ++ j) 14 for(int k = 1; k <= 11; ++ k) 15 ans.a[i][j] = (ans.a[i][j] + (x.a[i][k] * y.a[k][j]) % 7777777) % 7777777; 16 return ans; 17 } 18 19 Martix friend operator % (Martix x, int m) 20 { 21 for(int i = 1; i<= 11; ++ i) 22 for(int j = 1; j <= 11; ++ j) 23 x.a[i][j] = x.a[i][j] % m; 24 return x; 25 } 26 }; 27 int m, n; 28 LL f[15], sum[15]; 29 Martix ksm(Martix x, LL b, LL mod) 30 { 31 Martix ret; 32 memset(ret.a, 0, sizeof(ret.a)); 33 for(int i = 1; i <= m; ++ i) ret.a[1][i] = f[i]; 34 for(;b; b >>= 1, x = (x * x) % mod) 35 if(b & 1) ret = (ret * x) % mod; 36 return ret; 37 } 38 39 int main() 40 { 41 // freopen("fyfy.in","r",stdin); 42 // freopen("fyfy.out","w",stdout); 43 LL ans = 0; 44 Martix zy; 45 memset(zy.a, 0, sizeof(zy.a)); 46 scanf("%d%d", &m, &n); 47 if(n > m) 48 { 49 for(int i = 1; i <= m; ++ i) zy.a[i][m] = 1, f[i] = 1; 50 for(int i = 2; i <= m; ++ i) zy.a[i][i - 1] = 1; 51 for(int i = 1; i <= m; ++ i) 52 for(int j = 1; j < i; ++ j) 53 f[i] = f[i] + f[j]; 54 zy = ksm(zy, n - 1, 7777777); 55 // for(int i = 1; i <=m; ++ i) 56 // ans = (ans + ((long long)f[i] * zy.a[i][1]) % 7777777) % 7777777; 57 printf("%lld\n", zy.a[1][1]); 58 } 59 else 60 { 61 for(int i = 1; i <= n; ++ i) f[i] = sum[i - 1] + 1, sum[i] = sum[i - 1] + f[i]; 62 printf("%lld\n", f[n]); 63 } 64 return 0; 65 }
总结反思
考场上写Wa掉了,可我怎么也没想到是把转移矩阵和初始向量相乘的时候算错了,为了避免这个问题我们可以把初始向量放在快速幂的0次矩阵的第一行,这样就不会错了。