DP+组合数学典题
https://codeforces.com/contest/2041/problem/H
#include<bits/stdc++.h>
using namespace std;
#define x first
#define y second
#define int long long
#define endl '\n'
const int N=1e6+10,mod=998244353;
typedef pair<int,int> PII;
int fact[N],infact[N];
int qmi(int a,int k){
int res=1;
while(k){
if(k&1) res=res*a%mod;
a=a*a%mod;
k>>=1;
}
return res;
}
void init(){
fact[0]=infact[0]=1;
for(int i=1;i<N;i++) fact[i]=fact[i-1]*i%mod;
infact[N-1]=qmi(fact[N-1],mod-2);
for(int i=N-2;i>=1;i--) infact[i]=infact[i+1]*(i+1)%mod;
}
int C(int n,int m){
return fact[n]*infact[n-m]%mod*infact[m]%mod;
}
int f[N][2],sum[N][2];
/*
题意转换,相当于就是不能出现连续k个>或者<, =无关答案,所以我们可以枚举>和<的数量即可
f[i][1]:表示选i个符号,不考虑=,并且第i个符号结尾是1的方案数
f[i][0]:第i个符号结尾是0
转移:
枚举f[i][1]中1的连续出现的次数,不大于等于k次就行
f[i][1]=sum(f[j][0]),其中i-j<k,前缀和优化即可
然后再逐个考虑加上=之后的方案数数量即可
*/
void slove(){
int n,k;
cin>>n>>k;
if(k==1){
cout<<1<<endl;
return ;
}
n--;
f[1][1]=f[1][0]=sum[1][0]=sum[1][1]=1;
int ans=(C(n,1)*2%mod+1)%mod;
for(int i=2;i<=n;i++){
f[i][1]=(sum[i-1][0]-sum[max(i-k,0ll)][0]+mod)%mod;
f[i][0]=(sum[i-1][1]-sum[max(i-k,0ll)][1]+mod)%mod;
if(i<k) f[i][1]++,f[i][0]++;
sum[i][1]=(sum[i-1][1]+f[i][1])%mod;
sum[i][0]=(sum[i-1][0]+f[i][0])%mod;
ans+=(f[i][1]+f[i][0])%mod*C(n,i)%mod;
ans%=mod;
}
cout<<(ans+mod)%mod<<endl;
}
signed main(){
// ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
init();
int T=1;
// cin>>T;
while(T--) slove();
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架