【ZOJ3899】State Reversing

Description

有\(N\)个不同的怪兽,编号从\(1\) 到\(N\)。Yukari有\(M\)个相同的房间,编号为\(1\)到\(M\)。每个房间是无限大的,每个房间有两种状态:可以住或者不可以住(一开始所有的房间都可以住)。Yukari每天都会选定一个区间 \([l,r]\),把编号在这个区间的房间状态反转(可以住改成不可以住,不可以住改成可以住)。怪兽只能住在“可以住”的房间。每间“可以住”的房间至少有一个怪兽。

Yukari想知道,每次反转后,有多少种方法为这些怪兽分配房间。两种方法(方法\(A\)和方法\(B\))认为是同种方法当且仅当对于方案\(A\)中任意一个房间\(x\),在方案\(B\)中存在一个房间\(y\)使得房间\(x\)和房间\(y\)住的怪兽的编号集合是一样的。换句话说,房间是相同的。

Input

第一行一个整数 \(T(T≤5)\) ,表示数据组数。

接下来三个整数 \(N,M,Q(1≤M≤N≤10^5,Q≤10^5)\) ,分别表示怪兽数、房间数、操作次数。

接下来\(Q\)行,每行两个整数 \(l,r(1≤l≤r≤M)\) ,表示Yukari会反转区间 \([l,r]\) 的状态。

方案数对\(880803841\)取模

Output

对于每次操作,输出进行反转操作后为怪兽分配房间的方案数。


把\(n\)个有标号的球求放到\(m\)个无标号的非空盒子里,发现就是第二类斯特林数,因为\(m\)会变,所以等价于求斯特林行。

先考虑求出\(n\)个有标号的球出放到\(m\)个有标号的非空盒子里,即为\({n \brace m}m!\)

\[f_i={n \brace i}i!
\]

考虑进行容斥,设\(g_i\)代表\(n\)个有标号的球放到\(i\)个有标号的盒子里的方案数,则有

\[g_i=i^n
\]

显然有

\[g_k=\sum_{i=0}^k\binom{k}{i}f_i
\]

二项式反演

\[\begin{aligned}
f_k&=\sum_{i=0}^k(-1)^i\binom{k}{i}g_{k-i}\\
&=\sum_{i=0}^k(-1)^i\frac{k!}{(k-i)!i!}(k-i)^n\\
&=k!\sum_{i=0}^k\frac{(-1)^i}{i!}\frac{(k-i)^n}{(k-i)!}
\end{aligned}
\]

所以

\[{n\brace k}=\sum_{i=0}^k\frac{(-1)^i}{i!}\frac{(k-i)^n}{(k-i)!}
\]

然后卷一下子就行了,维护用个线段树就好


Code:

#include <cstdio>
#include <algorithm>
const int mod=880803841,G=26,Gi=711418487;
const int N=1e5+10;
#define add(a,b) ((a+b)%mod)
#define mul(a,b) (1ll*(a)*(b)%mod)
int qp(int d,int k){int f=1;while(k){if(k&1)f=mul(f,d);d=mul(d,d),k>>=1;}return f;}
int n,m,q,a[N<<3],b[N<<3],turn[N<<3],fac[N<<3],len,L;
void NTT(int *a,int typ)
{
for(int i=1;i<len;i++) if(i<turn[i]) std::swap(a[i],a[turn[i]]);
for(int le=1;le<len;le<<=1)
{
int wn=qp(typ?G:Gi,(mod-1)/(le<<1));
for(int p=0;p<len;p+=le<<1)
{
int w=1;
for(int i=p;i<p+le;i++,w=mul(w,wn))
{
int tx=a[i],ty=mul(w,a[i+le]);
a[i]=add(tx,ty);
a[i+le]=add(tx,mod-ty);
}
}
}
if(!typ)
{
int inv=qp(len,mod-2);
for(int i=0;i<len;i++) a[i]=mul(a[i],inv);
}
}
int sum[N<<2],tag[N<<2];
#define ls id<<1
#define rs id<<1|1
void build(int id,int l,int r)
{
tag[id]=0,sum[id]=r+1-l;
if(l==r) return;
int mid=l+r>>1;
build(ls,l,mid),build(rs,mid+1,r);
}
void pushdown(int id,int l,int r)
{
if(tag[id])
{
int mid=l+r>>1;
sum[ls]=mid+1-l-sum[ls];
sum[rs]=r-mid-sum[rs];
tag[ls]^=1,tag[rs]^=1,tag[id]^=1;
}
}
void change(int id,int L,int R,int l,int r)
{
if(L==l&&R==r)
{
sum[id]=R+1-L-sum[id];
tag[id]^=1;
return;
}
pushdown(id,L,R);
int Mid=L+R>>1;
if(r<=Mid) change(ls,L,Mid,l,r);
else if(l>Mid) change(rs,Mid+1,R,l,r);
else change(ls,L,Mid,l,Mid),change(rs,Mid+1,R,Mid+1,r);
sum[id]=sum[ls]+sum[rs];
}
int main()
{
int T;scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&m,&n,&q);
len=1,L=-1;
while(len<=m<<1) len<<=1,++L;
for(int i=0;i<len;i++) a[i]=b[i]=0,turn[i]=turn[i>>1]>>1|(i&1)<<L;
fac[0]=1;for(int i=1;i<=m;i++) fac[i]=mul(fac[i-1],i);
a[m]=b[m]=qp(fac[m],mod-2);
for(int i=m-1;~i;i--) b[i]=a[i]=mul(a[i+1],i+1);
for(int i=1;i<=m;i+=2) a[i]=mod-a[i];
for(int i=0;i<=m;i++) b[i]=mul(b[i],qp(i,m));
NTT(a,1),NTT(b,1);
for(int i=0;i<len;i++) a[i]=mul(a[i],b[i]);
NTT(a,0);
build(1,1,n);
for(int l,r,i=1;i<=q;i++)
{
scanf("%d%d",&l,&r);
change(1,1,n,l,r);
printf("%d\n",a[sum[1]]);
}
}
return 0;
}

2018.12.22

【ZOJ3899】State Reversing 解题报告的更多相关文章

  1. [ZOJ3899]State Reversing

    [ZOJ3899]State Reversing 试题描述 Yakumo Yukari is with no doubt one of the most powerful youkai in Gens ...

  2. ZOJ3899 State Reversing 【线段树 + NTT】

    题目链接 ZOJ3899 题解 比较累,做一道水题 还被卡常= = 我在\(ZOJ\)交过的两道\(NTT\)都被卡常了.. 哦,题意就是求第二类斯特林数,然后线段树维护一下集合数量就可以了 #inc ...

  3. USACO Section2.2 Party Lamps 解题报告 【icedream61】

    lamps解题报告------------------------------------------------------------------------------------------- ...

  4. USACO Section1.1 Friday the Thirteenth 解题报告

    friday解题报告 —— icedream61 博客园(转载请注明出处) -------------------------------------------------------------- ...

  5. HDU 4869 Turn the pokers (2014多校联合训练第一场1009) 解题报告(维护区间 + 组合数)

    Turn the pokers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  6. 2014-03-01 春季PAT 1073-1076解题报告

    今天下午的PAT考试状态不理想,回来怒刷了一遍,解题报告如下: 1073. Scientific Notation (20) 基本模拟题,将一长串的科学计数转换为普通的数字表示方式.思路是是数组存储输 ...

  7. 【LeetCode】838. Push Dominoes 解题报告(Python)

    [LeetCode]838. Push Dominoes 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http:// ...

  8. CH Round #56 - 国庆节欢乐赛解题报告

    最近CH上的比赛很多,在此会全部写出解题报告,与大家交流一下解题方法与技巧. T1 魔幻森林 描述 Cortana来到了一片魔幻森林,这片森林可以被视作一个N*M的矩阵,矩阵中的每个位置上都长着一棵树 ...

  9. 二模13day1解题报告

    二模13day1解题报告 T1.发射站(station) N个发射站,每个发射站有高度hi,发射信号强度vi,每个发射站的信号只会被左和右第一个比他高的收到.现在求收到信号最强的发射站. 我用了时间复 ...

随机推荐

  1. PHP的学习路线规划

    第一阶段:WEB的快速入门 前期入门学习我们需要学一些HTML+CSS+JS前端的一些技术,这个阶段不需要太深入的学习,学习到可以制作出一个像样点的静态页面就可以了.因为大家是学习PHP,对于新人来说 ...

  2. HTML基础范例

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. 出现 org.springframework.beans.factory.BeanCreationException 异常的原因及解决方法

    1 异常描述 在从 SVN 检出项目并配置完成后,启动 Tomcat 服务器,报出如下错误: 2 异常原因 通过观察上图中被标记出来的异常信息,咱们可以知道 org.springframework.b ...

  4. Cocos2dx源码赏析(4)之Action动作

    Cocos2dx源码赏析(4)之Action动作 本篇,依然是通过阅读源码的方式来简单赏析下Cocos2dx中Action动画的执行过程.当然,这里也只是通过这种方式来总结下对Cocos2dx引擎的理 ...

  5. tar.gz 文件解压 (安装 netbean 时会用到)

    sudo tar xvf jdk-7u45-linux-i586.tar.gz -C /usr/lib 参考文章 http://hi.baidu.com/xiaomeng008/item/5e787b ...

  6. 我眼中的PD(产品狗)

    以下内容可能引起您的不适(前方高能),请先移步科普: 产品经理为什么会存在? 本猿 -> web程序属 -> 前端开发种,从大森林迁徙到了小草原: 小草原物种稀缺,除了 程序猿,很难见到诸 ...

  7. [东北师大软工]Week2-作业2:个人项目实战 初步测试结果

    作业地址 https://edu.cnblogs.com/campus/nenu/2016SE_NENU/homework/1656 测试须知 测试机为Windows环境,所有提交到Coding.ne ...

  8. No.110_第三次团队会议

    前端的易帜 前端在整个软件中有着举足轻重的地位.前端设计一般可以理解为视觉设计,前端开发则是前台代码的实现. 随着科技水平的提高和生产力的提高,人民对于审美的要求逐渐增高.在没有科技壁垒的情况下,是否 ...

  9. C++:类中两个易被忽略的默认函数

    C++的自定义类中有六个默认的函数,即如果用户没有显式定义这些函数时,C++编译器会类中生成这些函数的默认形式.除了大家所熟知的构造函数.拷贝构造函数.赋值函数和析构函数外,C++为自定义类 还提供了 ...

  10. In-band Network Function Telemetry

    文章名称:In-band Network Function Telemetry 发表时间:2018 期刊来源:SIGCOMM I Introduction (介绍) NFV运行在商品服务器上,在网络功 ...