题解:AT_abc401_c [ABC401C] K-bonacci
思路
先用一个 fff 数组初始化前 kkk 个。
再用 sss 数组维护 fff 的前缀。
我们可以得到一个式子:
对于 m+1≤im + 1 \le im+1≤i,fi=(si−1−si−m−1)f_i=(s_{i-1}-s_{i-m-1})fi=(si−1−si−m−1)
否则 fi=si−1f_i=s_{i-1}fi=si−1。
然后统计 fff 的前缀。
做完了。
代码
//f(3,5)=4 f(4,5)=5 f(5,5)=1
//既然我求不出来答案,那么为什么我们不能回退?
//首先,最后一项等于1,然后推回去,能等于1的只有f(m,m)
//然后,我们对于f(m,m),就意思说有东西退出来了f(m,m),那只有f(m-1,m)和f(m^2,m)
//然后,这里出了两条分叉,直接按照是+1或者说/m来搜出来,对于每个子树,只要搜到了n层就推出
//时间复杂度O(2^n),一眼超时,现在问题变成了这样,我可以进行n次,每次可以考虑-1或者*m,求出总方案
//不过,我们可以枚举进行了多少次*m,-1的次数也知道了
//C(3,1)+C(3,0),3+1=4(因为只有t个*m,所以说n-t<=t)
//ans:sigma(0~n/2)C(n,i)
#include <bits/stdc++.h>
using namespace std;
long long mod = 1e9;
long long qmi(long long a,long long k){long long res = 1;while (k){if (k & 1){res = (res * a) % mod;}a = (a * a) % mod;k >>= 1;}return res;
}
const long long N = 1000010;
long long f[N];
long long s[N];
int main(){
// freopen("change.in","r",stdin);
// freopen("change.out","w",stdout);memset(s,0,sizeof s);memset(f,0,sizeof f);long long n,m;cin >> n >> m;if (n < m){cout << 1;return 0;}for (long long i = 0; i < m; i ++ ){f[i] = 1;}s[0] = f[0];for (long long i = 1; i < m; i ++ ){s[i] = s[i - 1] + f[i];s[i] %= mod;}for (long long i = m; i <= n; i ++ ){if (i - m - 1 >= 0){f[i] = (s[i - 1] - s[i - m - 1]) % mod;if (f[i] < 0){f[i] += mod;}}else{f[i] = s[i - 1] % mod;}s[i] = (s[i - 1] + f[i]) % mod;}cout << f[n] % mod;return 0;
}