[BZOJ5306] [HAOI2018]染色(容斥原理+NTT)
[BZOJ5306] [HAOI2018]染色(容斥原理+NTT)
题面
一个长度为 n的序列, 每个位置都可以被染成 m种颜色中的某一种.
如果n个位置中恰好出现了 S次的颜色有 K种, 则小 C 会产生 \(W_k\)的愉悦度.
求对于所有可能的染色方案, 他能获得的愉悦度的和。答案对 1004535809 取模
分析
显然颜色数量不超过\(tot=\min(m,\frac{n}{S})\)
我们需要求出现了\(S\)次的颜色有\(i\)种的方案数。这个东西不太好求,考虑容斥,求出现了\(S\)次的颜色有至少\(i\)种的方案数,记为\(t(i)\)
我们先从\(m\)种颜色里选出\(i\)种颜色,方案数\(C_m^i\)
然后从\(n\)个位置里选出\(S\)个位置,涂上颜色1。从剩下\(n-S\)个位置里选出\(S\)个位置,涂上颜色2。从剩下\(n-2S\)个位置里选出\(S\)个位置,涂上颜色3......从从剩下\(n-(i-1)S\)个位置里选出\(S\)个位置,涂上颜色i. 方案数为:
\]
这样涂完色之后还有\(n-iS\)个位置没涂,剩下\(m-i\)种颜色没用,方案数为\((m-i)^{n-iS}\)
因此,
\]
然后加上容斥,最终答案\(ans(i)\)为
\]
令\(A(i)=t(i)i!,B(i)=\frac{(-1)^{j-i}}{(j-i)!}\)
\]
由于\(j+j-i\)不是常数,不能直接卷积。类似[ZJOI2014]力,把B反转就能卷积了.
令\(B'(j)=B(tot-j)\),则\(B(j-i)=B'(tot-j+i)\)
\]
由于\(tot-j+i+j=tot+i\)为一常数,符合卷积的特征。注意最后的\(ans(i)i!\)实际上是\(A\)和\(B'\)卷积得到的多项式第\(tot+i\)项。最后别忘了除以\(i!\)并乘上\(W_i\)
代码
//https://www.luogu.org/problem/P4491
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define maxn 10000000
#define maxm 400000
#define G 3
#define mod 1004535809
#define invG 334845270
using namespace std;
typedef long long ll;
inline ll fast_pow(ll x,ll k){
	ll ans=1;
	while(k){
		if(k&1) ans=ans*x%mod;
		x=x*x%mod;
		k>>=1;
	}
	return ans;
}
inline ll inv(ll x){
	return fast_pow(x,mod-2);
}
void NTT(ll *x,int n,int type){
	static int rev[maxm+5];
	int tn=1,k=0;
	while(tn<n){
		tn*=2;
		k++;
	}
	for(int i=0;i<n;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(k-1));
	for(int i=0;i<n;i++) if(i<rev[i]) swap(x[i],x[rev[i]]);
	for(int len=1;len<n;len*=2){
		int sz=len*2;
		ll gn1=fast_pow((type==1?G:invG),(mod-1)/sz);
		for(int l=0;l<n;l+=sz){
			int r=l+len-1;
			ll gnk=1;
			for(int i=l;i<=r;i++){
				ll tmp=x[i+len];
				x[i+len]=(x[i]-gnk*tmp%mod+mod)%mod;
				x[i]=(x[i]+gnk*tmp%mod)%mod;
				gnk=gnk*gn1%mod;
			}
		}
	}
	if(type==-1){
		ll invn=inv(n);
		for(int i=0;i<n;i++) x[i]=x[i]*invn%mod;
	}
}
void mul(ll *a,ll *b,ll *ans,int n){
	NTT(a,n,1);
	NTT(b,n,1);
	for(int i=0;i<n;i++) ans[i]=a[i]*b[i]%mod;
	NTT(ans,n,-1);
}
ll fact[maxn+5],invfact[maxn+5];
void ini_fact(int n){
	fact[0]=1;
	for(int i=1;i<=n;i++) fact[i]=fact[i-1]*i%mod;
	invfact[n]=inv(fact[n]);
	for(int i=n-1;i>=0;i--) invfact[i]=invfact[i+1]*(i+1)%mod;
}
inline ll C(int n,int m){
	return fact[n]*invfact[n-m]%mod*invfact[m]%mod;
} 
int n,m,s;
ll w[maxm+5];
ll a[maxm+5],b[maxm+5],sum[maxm+5];
int main(){
//	printf("%lld\n",inv(3));
	scanf("%d %d %d",&n,&m,&s);
	for(int i=0;i<=m;i++) scanf("%lld",&w[i]);
	ini_fact(max(n,m));
	int lim=min(n/s,m);
	int dn=1;
	while(dn<=(lim+1)*2) dn*=2;
	for(int i=0;i<=lim;i++){
		a[i]=C(m,i)*fact[n]%mod*inv(fast_pow(fact[s],i))%mod*invfact[n-s*i]%mod*fast_pow(m-i,n-s*i)%mod*fact[i]%mod;
		//f(x)=C(m,i)*(n!)/((s!)^i(n-si)!)*(m-i)^(n-si)
		//A(x)=f(x)x!
	}
	for(int i=0;i<=lim;i++){
		b[i]=(fast_pow(-1,lim-i)*invfact[lim-i]%mod+mod)%mod;
		//B(x)=(-1)^x/x!
		//类似[ZJOI2014]力,要把B反转
	}
	mul(a,b,sum,dn);
	ll ans=0;
	for(int i=0;i<=lim;i++){
		ans=(ans+sum[i+lim]*invfact[i]%mod*w[i]%mod)%mod;
	}
	printf("%lld\n",ans);
}
												
											[BZOJ5306] [HAOI2018]染色(容斥原理+NTT)的更多相关文章
- 【BZOJ5306】[HAOI2018]染色(NTT)
		
[BZOJ5306]染色(NTT) 题面 BZOJ 洛谷 题解 我们只需要考虑每一个\(W[i]\)的贡献就好了 令\(lim=min(M,\frac{N}{S})\) 那么,开始考虑每一个\(W[i ...
 - BZOJ5306 HAOI2018染色(容斥原理+NTT)
		
容易想到枚举恰好出现S次的颜色有几种.如果固定至少有i种恰好出现S次,那么方案数是C(M,i)·C(N,i*S)·(M-i)N-i*S·(i*S)!/(S!)i,设为f(i). 于是考虑容斥,可得恰好 ...
 - [HAOI2018][bzoj5306] 染色 [容斥原理+NTT]
		
题面 传送门 思路 这道题的核心在于"恰好有$k$种颜色占了恰好$s$个格子" 这些"恰好",引导我们去思考,怎么求出总的方案数呢? 分开考虑 考虑把恰好有$s ...
 - BZOJ5306  [HAOI2018]染色  【组合数 + 容斥 + NTT】
		
题目 为了报答小 C 的苹果, 小 G 打算送给热爱美术的小 C 一块画布, 这块画布可 以抽象为一个长度为 \(N\) 的序列, 每个位置都可以被染成 \(M\) 种颜色中的某一种. 然而小 C 只 ...
 - [BZOJ5306][HAOI2018]染色
		
bzoj luogu Description 给一个长度为\(n\)的序列染色,每个位置上可以染\(m\)种颜色.如果染色后出现了\(S\)次的颜色有\(k\)种,那么这次染色就可以获得\(w_k\) ...
 - [BZOJ5306][HAOI2018]染色(容斥+FFT)
		
https://www.cnblogs.com/zhoushuyu/p/9138251.html 注意如果一开始F(i)中内层式子中j枚举的是除前i种颜色之外还有几种出现S次的颜色,那么后面式子就会难 ...
 - 【BZOJ5306】 [Haoi2018]染色
		
BZOJ5306 [Haoi2018]染色 Solution xzz的博客 代码实现 #include<stdio.h> #include<stdlib.h> #include ...
 - 【题解】[HAOI2018]染色(NTT+容斥/二项式反演)
		
[题解][HAOI2018]染色(NTT+容斥/二项式反演) 可以直接写出式子: \[ f(x)={m \choose x}n!{(\dfrac 1 {(Sx)!})}^x(m-x)^{n-Sx}\d ...
 - BZOJ 5306 [HAOI2018] 染色
		
BZOJ 5306 [HAOI2018] 染色 首先,求出$N$个位置,出现次数恰好为$S$的颜色至少有$K$种. 方案数显然为$a_i=\frac{n!\times (m-i)^{m-i\times ...
 
随机推荐
- vue 设置 input 为不可以编辑
			
我用最笨的方法,先实现功能先,用两个input,一个可以编辑,一个不可以编辑,失去焦点后隐藏可以点击的那个,点"编辑"时,显示可以编辑的那个input <div class= ...
 - 学习经常遇到的浮动(float)
			
参考自 小辉随笔: https://www.cnblogs.com/lchsirblog/p/9582989.html 一.什么时候需要使用浮动 最常见的情景是:多个块级元素(如div)需要同一行显示 ...
 - httpClient和RestTemplate的使用
			
1.httpClient的使用 <dependency> <groupId>org.apache.httpcomponents</groupId> <arti ...
 - MongoDB基本操作(增删改查)
			
基本操作 基本的“增删查改“,在DOS环境下输入mongo命令打开shell,其实这个shell就是mongodb的客户端,同时也是一个js的编译器,默认连接的是“test”数据库.
 - Spring Boot教程(二)关于RabbitMQ服务器整合
			
准备工作 15min IDEA maven 3.0 在开始构建项目之前,机器需要安装rabbitmq,你可以去官网下载,http://www.rabbitmq.com/download.html ,如 ...
 - @清晰掉 string.h之基础堵漏
			
一个标准的strcpy函数: 原本以为自己对strcpy还算比较了解,结果面试时还是悲剧了. 下面给出网上strcpy的得分版本: 2分 void strcpy( char *strDest, cha ...
 - Android传感器【转】
			
本文转载自:http://blog.csdn.net/ffmxnjm/article/details/52101592?locationNum=3&fps=1 传感器的意义 事实上,目前智能手 ...
 - Sqlserver 创建账号
			
下面是通过脚本创建账号,创建一个appuser 的账号,密码:123456,可操作的DB:TEST 赋予权限,增删改查,操作视图,存储过程.当然当前的账号要有足够的权限. create login a ...
 - maven的配置及使用
			
Maven项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的软件项目管理工具. Apache官网下载maven 解压缩,配置环境变量: path路径:E:\apache-ma ...
 - VBA通过C#以API方式调用JS脚本函数
			
http://www.cnblogs.com/Charltsing/p/JSDotNetAPI.html 在网页采集中,很多时候需要运行网站下载的某个js文件中的函数,以计算Request参数.VBA ...