牛客多校第八场
题目链接
一个使用容斥思想的题目
官方给出的题解:
这里我使用的转移方法和官方给出的不同,用dp[i] 表示经过第i个障碍物所不合法的方案数
而计算后面障碍物的方案数时我们得把之前计算的方案数的一部分先减去,因为之前的障碍可以走到当前的障碍.所以当前非法的方案数中有一部分已经计算过一次
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 998244353;
const int N = 30000 + 10;
const int M = 1e7 + 6;
struct node {int x, y; }T[N];
bool cmp(node a, node b){return a.x < b.x; }
int pre[M],fac[M],sum[M];
int quick(int a, int b){
a %= mod;
int ans = 1;
while(b){
if(b&1){
ans = ans*a%mod;
}
b >>= 1;
a = a*a%mod;
}
return ans;
}
void init(){
fac[0] = 1;
for(int i = 1; i < M; i ++){
fac[i] = i * fac[i - 1]%mod;
}
}
int C(int n , int m){
if(n < 0 || m < 0||n < m) return 0;
return fac[n]*quick(fac[m]*fac[n - m], mod - 2)%mod;
}
int dp[N];
signed main()
{
init();
int L, d ,m;
cin >> L >> d >>m;
for(int i = 0; i < m; i ++){
cin >> T[i].x >> T[i].y;
}
pre[0]= sum[0] = 1;
for(int i = 1; i <= L; i ++){
if(i < d) pre[i] = 0;
else pre[i] = sum[i - d];
sum[i] = (sum[i - 1] + pre[i])%mod;// sum[i] = sum[i - d] + sum[i - d - 1] + …… + sum[0] = sum[i - d] + sum[i - 1]
}
sort(T, T + m,cmp);
int ans = pre[L];
for(int i = 0; i < m; i ++){
node a = T[i];
dp[i] = C(a.y - a.x*d + a.x - 1 , a.x - 1);
for(int j = 0; j < i ; j ++){
node b = T[j];
int temp = dp[j]*C((a.y - b.y) - (a.x - b.x)*d +(a.x - b.x) - 1 , (a.x - b.x) - 1)%mod;
dp[i] = (dp[i] - temp + mod)%mod;
}
// cout << dp[i] << endl;
ans = (ans - dp[i]*pre[L - a.y]%mod + mod)%mod;
}
cout << ans << endl;
}