这题在vp的时候做出来了,但是今天在做2023CCPC秦皇岛的热身赛的时候发现这道题又想了很久才做出来,于是决定还是把思路写一遍
链接
题意
给一个长为
解
最长连续的1的个数为
由容斥原理可以知道最长连续1的个数为
这种不超过多少的问题可以转化为一个多元方程,例如这个题可以转化为
的解的个数,其中
但这样搞需要遍历
可以想到一个类似的但较弱的问题(想不起来具体是什么,只记得可以将一些元素绑定起来然后用隔板法解决),然后给了某种启发。
原序列中有
AC代码:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int long long
typedef unsigned long long ull;
#define dmp(x) cerr<<"DEBUG"<<__LINE__<<":"<<#x<<" "<<x<<endl
const ll INF=0x3f3f3f3f3f3f3f3fLL;
typedef pair<int,int> pii;
const int mod=998244353;
const int N=1e5+100;
int fac[N],rev[N];
(ll a,ll n,ll m)
ll qpow{
=1;
ll answhile(n)
{
if(n&1)
=(__int128_t)ans*a%m;
ans=(__int128_t)a*a%m;
a>>=1;
n}
return ans;
}
void init(int n)
{
[0]=1;
facfor(int i=1;i<=n;i++)
[i]=fac[i-1]*i%mod;
fac[n]=qpow(fac[n],mod-2,mod);//n must be less than mod
revfor(int i=n;i>=1;i--)
[i-1]=rev[i]*i%mod;
revassert(rev[0]==1);
}
int C(int n,int m)
{
if(m>n)
return 0;
return fac[n]*rev[m]%mod*rev[n-m]%mod;
}
inline int cal(int n,int m,int k){
int ans=0;
for(int i=0;i*(k+1)<=m;i++){
=(ans+(i%2==0?1:-1)*C(n-m+1,i)%mod*C(n-i*(k+1),n-m)%mod)%mod;
ans}
return ans;
}
signed main() {
::sync_with_stdio(false);cin.tie(0);
iosint n,m,k;
>>n>>m>>k;
cin(1e5+10);
initif(!(m<=n&&k<=m)){
<<0<<'\n';
coutreturn 0;
}
if(k==0){
if(m==0)
<<1<<'\n';
coutelse
<<0<<'\n';
coutreturn 0;
}
<<((cal(n,m,k)-cal(n,m,k-1))%mod+mod)%mod<<'\n';
coutreturn 0;
}