[ZOJ3899]State Reversing

Posted jefflyy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[ZOJ3899]State Reversing相关的知识,希望对你有一定的参考价值。

题意:有$N$个互不相同的物品和$M$个房间,初始时每个房间都可用,有$D$次修改$(l,r)$,表示将第$l$个房间到第$r$个房间的状态翻转(可用$\Leftrightarrow$不可用),并询问把物品放到房间(不能有空房,房间视作相同的)的方案数

之前鸽了,今天去ZOJ看发现居然是车万题,有奇妙的感觉

直接用线段树维护,答案是第二类斯特林数,预处理一下就好了,原根应该是只能暴力求的==

紫妈

#include<stdio.h>
#include<string.h>
typedef long long ll;
const int mod=880803841;//g=26
int mul(int a,int b){return a*(ll)b%mod;}
int ad(int a,int b){return(a+b)%mod;}
int de(int a,int b){return(a-b)%mod;}
int pow(int a,int b){
	int s=1;
	while(b){
		if(b&1)s=mul(s,a);
		a=mul(a,a);
		b>>=1;
	}
	return s;
}
int rev[262144],N,iN;
void pre(int n){
	int i,k;
	for(N=1,k=0;N<n;N<<=1)k++;
	for(i=0;i<N;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(k-1));
	iN=pow(N,mod-2);
}
void swap(int&a,int&b){a^=b^=a^=b;}
void ntt(int*a,int on){
	int i,j,k,t,w,wn;
	for(i=0;i<N;i++){
		if(i<rev[i])swap(a[i],a[rev[i]]);
	}
	for(i=2;i<=N;i<<=1){
		wn=pow(26,(on==1)?(mod-1)/i:(mod-1-(mod-1)/i));
		for(j=0;j<N;j+=i){
			w=1;
			for(k=0;k<i>>1;k++){
				t=mul(w,a[i/2+j+k]);
				a[i/2+j+k]=de(a[j+k],t);
				a[j+k]=ad(a[j+k],t);
				w=mul(w,wn);
			}
		}
	}
	if(on==-1){
		for(i=0;i<N;i++)a[i]=mul(a[i],iN);
	}
}
int s[400010],r[400010];
void build(int l,int r,int x){
	::r[x]=0;
	s[x]=r-l+1;
	if(l==r)return;
	int mid=(l+r)>>1;
	build(l,mid,x<<1);
	build(mid+1,r,x<<1|1);
}
void pushup(int x){s[x]=s[x<<1]+s[x<<1|1];}
void gao(int x,int len){
	r[x]^=1;
	s[x]=len-s[x];
}
void pushdown(int x,int ln,int rn){
	if(r[x]){
		gao(x<<1,ln);
		gao(x<<1|1,rn);
		r[x]=0;
	}
}
void modify(int L,int R,int l,int r,int x){
	if(L<=l&&r<=R)return gao(x,r-l+1);
	int mid=(l+r)>>1;
	pushdown(x,mid-l+1,r-mid);
	if(L<=mid)modify(L,R,l,mid,x<<1);
	if(mid<R)modify(L,R,mid+1,r,x<<1|1);
	pushup(x);
}
int a[262144],b[262144],fac[100010],rfac[100010];
int main(){
	int T,n,m,q,i,l,r;
	fac[0]=1;
	for(i=1;i<=100000;i++)fac[i]=mul(fac[i-1],i);
	rfac[100000]=pow(fac[100000],mod-2);
	for(i=100000;i>0;i--)rfac[i-1]=mul(rfac[i],i);
	scanf("%d",&T);
	while(T--){
		scanf("%d%d%d",&m,&n,&q);
		memset(a,0,sizeof(a));
		memset(b,0,sizeof(b));
		build(1,n,1);
		pre((m+1)<<1|1);
		for(i=0;i<=m;i++){
			a[i]=(i&1?-1:1)*rfac[i];
			b[i]=mul(pow(i,m),rfac[i]);
		}
		ntt(a,1);
		ntt(b,1);
		for(i=0;i<N;i++)a[i]=mul(a[i],b[i]);
		ntt(a,-1);
		for(i=m+1;i<N;i++)a[i]=0;
		while(q--){
			scanf("%d%d",&l,&r);
			modify(l,r,1,n,1);
			if(s[1]>m)
				puts("0");
			else
				printf("%d\n",(a[s[1]]+mod)%mod);
		}
	}
}

以上是关于[ZOJ3899]State Reversing的主要内容,如果未能解决你的问题,请参考以下文章

[ZOJ3899]State Reversing

ZOJ 3471(状态压缩DP)

ZOJ - 3471 Most Powerful (状态压缩)

zoj 3471 Most Powerful 状压dp

HDU 3899 树形DP||树上递推

P3899 [湖南集训]谈笑风生