测评会员优惠活动进行中 · 开通 VIP,有效期内测评不限次 VIP 优惠中 · 测评不限次 立即查看

A40205. 蓝跳跳

填空题 困难

题目描述

蓝跳跳

题目描述

小蓝制作了一个机器人,取名为蓝跳跳,因为这个机器人走路的时候基本靠跳跃。


蓝跳跳可以跳着走,也可以掉头。蓝跳跳每步跳的距离都必须是整数,每步可以跳不超过 k 的长度。由于蓝跳跳的平衡性设计得不太好,如果连续两次都是跳跃,而且两次跳跃的距离都至少是 p,则蓝跳跳会摔倒,这是小蓝不愿意看到的。


小蓝接到一个特别的任务,要在一个长为 L 舞台上展示蓝跳跳。小蓝要控制蓝跳跳从舞台的左边走到右边,然后掉头,然后从右边走到左边,然后掉头,然后再从左边走到右边,然后掉头,再从右边走到左边,然后掉头,如此往复。


为了让观者不至于太无趣,小蓝决定让蓝跳跳每次用不同的方式来走。小蓝将蓝跳跳每一步跳的距离记录下来,按顺序排成一列,显然这一列数每个都不超过 k 且和是 L。这样走一趟就会出来一列数。如果两列数的长度不同,或者两列数中存在一个位置数值不同,就认为是不同的方案。


请问蓝跳跳在不摔倒的前提下,有多少种不同的方案从舞台一边走到另一边。

输入描述

输入一行包含三个整数 k, p, L。

输出描述

输出一个整数,表示答案。答案可能很大,请输出答案除以 20201114的余数。

参考答案

#include <iostream> #include <cstring> using namespace std; const int N = 2e3 ; typedef long long ll; const ll mod = 20201114; ll f[1005][2]; ll p,k,l; ll A[N]; ll B[N][N]; ll tmp1[N],tmp2[N][N]; void multi(ll B[N][N], ll A[N] , ll C[N]) { memset(tmp1,0,sizeof(tmp1)); for(int i = 0 ; i < k << 1 ; i ++) { for(int j = 0 ; j < k << 1; j ++) { tmp1[i] = (tmp1[i] + B[i][j] * A[j] % mod ) % mod; } } memcpy(C,tmp1,sizeof(tmp1)); } void multi(ll A[N][N] , ll B[N][N] , ll C[N][N]) { memset(tmp2,0,sizeof(tmp2)); for(int i = 0 ; i < k << 1 ; i ++) for(int j = 0 ; j < k << 1 ; j ++) for(int m = 0 ; m < k << 1 ; m ++) tmp2[i][j] = (tmp2[i][j] + A[i][m] * B[m][j] % mod) % mod; memcpy(C,tmp2,sizeof(tmp2)); } void print(ll A[N]) { for(int i = 0 ; i < k << 1 ; i ++) printf("%lld " , A[i]); puts(""); } void print(ll A[N][N]) { for(int i = 0 ; i < k << 1 ; i ++) { for(int j = 0 ; j < k << 1 ; j ++) printf("%lld ",A[i][j]); puts(""); } } int main() { cin>>k>>p>>l; f[0][0] = 1; for(int i = 1 ; i <= k ; i ++) { for(int j = 1 ; j < p && j <= i; j ++) { f[i][0] = (f[i][0] + (f[i-j][0] + f[i-j][1]) % mod ) % mod; } for(int j = p ; j <= k && j <= i; j ++) { f[i][1] = (f[i][1] + f[i-j][0]) % mod; } } if(l <= k) { cout<<(f[l][0] + f[l][1])%mod; return 0; } for(int i = 0 ; i < k ; i ++) { A[i<<1] = f[k-i][1]; A[i<<1|1] = f[k-i][0]; } for(int i = (k<<1) -1 ; i >= (p<<1) - 1 ; i -= 2) B[0][i] = 1; for(int i = 0 ; i < (p - 1)<<1 ; i ++) B[1][i] = 1; for(int i = 2 ; i < k << 1 ; i ++) B[i][i-2] = 1; l -= k; while(l) { if(l & 1) multi(B,A,A); l >>= 1; multi(B,B,B); } printf("%lld\n",(A[0] + A[1]) % mod); return 0; }
上一题 下一题