题解:AT_ndpc2026_q 区間の和集合
更好的阅读体验
官解怎么是,拉插优化一坨东西,已吓哭。
然而并不需要,只要最基础的容斥 /qiang
题目就是,给你一堆区间,对于每个
那么首先简单转换一下,变成未被覆盖的区域大小恰好是
那么可以容斥。假设
那么我们考虑计算
容易发现转移所需要的
这是一个区间乘法求区间和的问题,线段树维护即可。然后由于
很显然我们可以利用
假设
#include<bits/stdc++.h>
#define endl '\n'
#define N 4006
#define MOD 998244353
using namespace std;
inline void add(int &x,int y) {x+=y,x-=x>=MOD?MOD:0;}
inline void dec(int &x,int y) {x+=MOD-y,x-=x>=MOD?MOD:0;}
inline void mul(int &x,int y) {x=1ll*x*y%MOD;}
int n,m,fac[N],ifac[N],pw2[N],old_f[N],f[N],cnt[N],g[N],h[N];
vector<int> vec[N];
struct Segtree {
int tree[N<<2],tag[N<<2];
void build(int p,int l,int r)
{
tag[p]=1;
if(l==r)return tree[p]=old_f[l],(void)0;
int mid=l+r>>1;
build(p<<1,l,mid),build(p<<1|1,mid+1,r);
tree[p]=(tree[p<<1]+tree[p<<1|1])%MOD;
}
inline void addtag(int p,int x) {mul(tree[p],x),mul(tag[p],x);}
inline void push_down(int p) {addtag(p<<1,tag[p]),addtag(p<<1|1,tag[p]),tag[p]=1;}
void update(int p,int l,int r,int L,int R,int x)
{
if(L<=l&&r<=R)return addtag(p,x);
push_down(p); int mid=l+r>>1;
if(L<=mid)update(p<<1,l,mid,L,R,x);
if(R>mid)update(p<<1|1,mid+1,r,L,R,x);
tree[p]=(tree[p<<1]+tree[p<<1|1])%MOD;
}
int query(int p,int l,int r,int L,int R)
{
if(L<=l&&r<=R)return tree[p];
push_down(p); int mid=l+r>>1,ret=0;
if(L<=mid)add(ret,query(p<<1,l,mid,L,R));
if(R>mid)add(ret,query(p<<1|1,mid+1,r,L,R));
return ret;
}
} T;
main()
{
scanf("%d%d",&n,&m),pw2[0]=fac[0]=1;
for(int i=1;i<N;i++)
pw2[i]=2ll*pw2[i-1]%MOD,fac[i]=1ll*i*fac[i-1]%MOD;
auto qpow=[](int x,int y=MOD-2) {
int ret=1;
for(;y;y>>=1,x=1ll*x*x%MOD)if(y&1)ret=1ll*ret*x%MOD;
return ret;
};
ifac[N-1]=qpow(fac[N-1]);
for(int i=N-2;~i;i--)ifac[i]=1ll*ifac[i+1]*(i+1)%MOD;
auto binom=[](int x,int y) {
return (x<y||x<0||y<0)?0:1ll*fac[x]*ifac[y]%MOD*ifac[x-y]%MOD;
};
for(int i=1,l,r;i<=n;i++)
scanf("%d%d",&l,&r),vec[r].push_back(l),cnt[l]++;
for(int i=m;~i;i--)add(cnt[i],cnt[i+1]);
f[0]=1,add(g[0],pw2[n]);
for(int j=1;j<=m;j++)
{
for(int i=0;i<=m;i++)old_f[i]=f[i],f[i]=0;
T.build(1,0,m);
for(int i=j;i<=m;i++)
{
f[i]=T.query(1,0,m,0,i-1),add(g[j],1ll*f[i]*pw2[cnt[i+1]]%MOD);
for(int k:vec[i])T.update(1,0,m,0,k-1,2);
}
}
for(int i=0;i<=m;i++)
for(int k=i;k<=m;k++)(k^i)&1?dec(h[i],1ll*g[k]*binom(k,i)%MOD):add(h[i],1ll*g[k]*binom(k,i)%MOD);
for(int i=1;i<=m;i++)printf("%d\n",h[m-i]);
return 0;
}