实用指南:题解:AT_abc401_c [ABC401C] K-bonacci
2025-10-23 11:44 tlnshuju 阅读(0) 评论(0) 收藏 举报思路
先用一个 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;
}
浙公网安备 33010602011771号