【AGC005F】Many Easy Problems FFT 容斥原理
题目大意
给你一棵树,有\(n\)个点。还给你了一个整数\(k\)。
设\(S\)为树上某些点的集合,定义\(f(S)\)为最小的包含\(S\)的联通子图的大小。
\(n\)个点选\(k\)个点一共有\(\binom{n}{k}\)中方案,请你求出所有方案的\(f(S)\)的和\(\mod 924844033\)。
出题人觉得这样就太简单了,他决定让你求出所有\(k=1\ldots n\)的答案。
\(n\leq 200000\)
题解
似乎对于每个\(k\)没办法快速求出答案。
我们考虑一个点对所有答案的贡献。
一个点\(x\)在这个联通子图内当且经当这\(k\)个点不在以\(x\)为根时\(x\)的子树内。
那么贡献为\(\binom{n}{k}-\sum \binom{a_i}{k}\),其中\(a_i\)为以\(x\)为根时各个子树的大小。可以发现,计算总的贡献时每条边两端的子树大小都会被计算一次。\(\binom{n}{k}\)会被计算\(n\)次。
设
\begin{cases}
n~~~~~~~~~~(i=n)\\
num_i~~~(i\neq n)
\end{cases}
\]
其中\(num_i\)为大小为\(i\)的子树的个数
ans_k&=\sum_{i\geq k} b_i\binom{i}{k}\\
&=\sum_{i\geq k} b_i\frac{i!}{(i-k)!k!}\\
&=\frac 1{k!}\sum_{i\geq k}b_ii!\times \frac{1}{(i-k)!}
\end{align}
\]
这可以转化成卷积的形式
c_{n-i}&=num_ii!\\
d_{i}&=\frac{1}{i!}\\
a_i&=\sum_{j+k=i}c_id_i\\
ans_i&=\frac{a_{n-i}}{i!}
\end{align}
\]
时间复杂度:\(O(n\log n)\)
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
#include<list>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
const ll p=924844033;
const ll g=5;
ll fp(ll a,ll b)
{
	ll s=1;
	while(b)
	{
		if(b&1)
			s=s*a%p;
		a=a*a%p;
		b>>=1;
	}
	return s;
}
namespace ntt
{
	ll w1[1000010];
	ll w2[1000010];
	int rev[1000010];
	int n;
	void init()
	{
#ifdef DEBUG
		n=16;
#else
		n=524288;
#endif
		int i;
		for(i=1;i<=n;i<<=1)
		{
			w1[i]=fp(g,(p-1)/i);
			w2[i]=fp(w1[i],p-2);
		}
		rev[0]=0;
		for(i=1;i<n;i++)
			rev[i]=(rev[i>>1]>>1)|(i&1?n>>1:0);
	}
	void ntt(ll *a,int t)
	{
		int i,j,k;
		ll u,v,w,wn;
		for(i=0;i<n;i++)
			if(rev[i]<i)
				swap(a[i],a[rev[i]]);
		for(i=2;i<=n;i<<=1)
		{
			wn=(t==1?w1[i]:w2[i]);
			for(j=0;j<n;j+=i)
			{
				w=1;
				for(k=j;k<j+i/2;k++)
				{
					u=a[k];
					v=a[k+i/2]*w%p;
					a[k]=(u+v)%p;
					a[k+i/2]=(u-v)%p;
					w=w*wn%p;
				}
			}
		}
		if(t==-1)
		{
			ll inv=fp(n,p-2);
			for(i=0;i<n;i++)
				a[i]=a[i]*inv%p;
		}
	}
};
ll b[1000010];
ll c[1000010];
ll a[1000010];
ll inv[1000010];
ll fac[1000010];
ll ifac[1000010];
int s[1000010];
int n;
list<int> l[200010];
ll num[1000010];
void dfs(int x,int fa)
{
	s[x]=1;
	for(auto v:l[x])
		if(v!=fa)
		{
			dfs(v,x);
			s[x]+=s[v];
			num[s[v]]--;
			num[n-s[v]]--;
		}
}
int main()
{
#ifdef DEBUG
	freopen("b.in","r",stdin);
	freopen("b.out","w",stdout);
#endif
	scanf("%d",&n);
	int i,x,y;
	for(i=1;i<=n-1;i++)
	{
		scanf("%d%d",&x,&y);
		l[x].push_back(y);
		l[y].push_back(x);
	}
	inv[0]=inv[1]=fac[0]=fac[1]=ifac[0]=ifac[1]=1;
	for(i=2;i<=n;i++)
	{
		inv[i]=-(p/i)*inv[p%i]%p;
		fac[i]=fac[i-1]*i%p;
		ifac[i]=ifac[i-1]*inv[i]%p;
	}
	dfs(1,0);
	num[n]=n;
	for(i=0;i<=n;i++)
		b[i]=num[n-i]*fac[n-i]%p;
	for(i=0;i<=n;i++)
		c[i]=ifac[i];
	ntt::init();
	ntt::ntt(b,1);
	ntt::ntt(c,1);
	for(i=0;i<ntt::n;i++)
		a[i]=b[i]*c[i]%p;
	ntt::ntt(a,-1);
	for(i=1;i<=n;i++)
	{
		ll ans=a[n-i]*ifac[i]%p;
		ans=(ans+p)%p;
		printf("%lld\n",ans);
	}
	return 0;
}
【AGC005F】Many Easy Problems FFT 容斥原理的更多相关文章
- AGC005F Many Easy Problems(NTT)
		先只考虑求某个f(k).考虑转换为计算每条边的贡献,也即该边被所选连通块包含的方案数.再考虑转换为计算每条边不被包含的方案数.这仅当所选点都在该边的同一侧.于是可得f(k)=C(n,k)+ΣC(n,k ... 
- 【AtCoder】AGC005F - Many Easy Problems
		题解 我们把一个点的贡献转化为一条边的贡献,因为边的数量是点的数量-1,最后再加上选点方案数\(\binom{n}{k}\)即可 一条边的贡献是\(\binom{n}{k} - \binom{a}{k ... 
- [AGC005F] Many Easy Problems
		link 题意简述 给定一颗无根树,对于所有大小为 $i$ 的点集,求出能够包含它的所有联通块之和,定义为 $f_i$ ,答案对 $924844033$ 取模. $n\leq 2\times 10^5 ... 
- 解题:AT2064 Many Easy Problems&EXNR #1 T3 两开花
		题面 两道题比较像,放在一起写了,后者可以看成前者的加强版 (sto ztb orz) 先看AT那道题 考虑计算每个点的贡献,用容斥计算:每个点没有贡献当且仅当选的所有点都在以他为根时的一个子节点的子 ... 
- Codeforces 913D - Too Easy Problems
		913D - Too Easy Problems 思路:二分check k 代码: #include<bits/stdc++.h> using namespace std; #define ... 
- 【AtCoder】AGC005 F - Many Easy Problems 排列组合+NTT
		[题目]F - Many Easy Problems [题意]给定n个点的树,定义S为大小为k的点集,则f(S)为最小的包含点集S的连通块大小,求k=1~n时的所有点集f(S)的和取模92484403 ... 
- 【CodeForces】913 D. Too Easy Problems
		[题目]D. Too Easy Problems [题意]给定n个问题和总时限T,每个问题给定时间ti和限制ai,当解决的问题数k<=ai时问题有效,求在时限T内选择一些问题解决的最大有效问题数 ... 
- AtcoderGrandContest 005 F. Many Easy Problems
		$ >AtcoderGrandContest \space 005 F. Many Easy Problems<$ 题目大意 : 有一棵大小为 \(n\) 的树,对于每一个 \(k \i ... 
- 【bzoj3771】Triple  FFT+容斥原理
		题目描述 樵夫的每一把斧头都有一个价值,不同斧头的价值不同.总损失就是丢掉的斧头价值和. 他想对于每个可能的总损失,计算有几种可能的方案. 注意:如果水神拿走了两把斧头a和b,(a,b)和(b,a)视 ... 
随机推荐
- nginx Location 语法基础知识
			URL地址匹配是Nginx配置中最灵活的部分 Location 支持正则表达式匹配,也支持条件匹配,用户可以通过location指令实现Nginx对动丶静态网页的过滤处理. Nginx locatio ... 
- c++入门之const初步理解
			关于const,首先建立这样的一个认识:const并不是定义了一个常量,而是定义了在某种环境下只读的变量.下面我们来区分一些东西: ; const int*p = # *p = ; i ... 
- SoftWater——SDN+UnderWater系列论文一
			---- SoftWater: Software-defined networking for next-generation underwater communication systems 来源: ... 
- MongoDB——待整理
			MongoDB mongoose——http://mongoosejs.com/ npm i mongoose Mongoose 通过外键与另一张表建立关联:Mongoose Populate 基本使 ... 
- python 3.6.1 安装scrapy踩坑之旅
			系统环境:win10 64位系统安装 python基础环境配置不做过多的介绍 window环境安装scrapy需要依赖pywin32,下载对应python版本的exe文件执行安装,下载的pywin32 ... 
- [转帖]Office全版本零售版转换VOL
			Office全版本零售版转换VOL https://blog.51cto.com/10981246/2062137 转成bat 执行 改天试试 @ECHO OFF&PUSHD %~DP0 ... 
- day 7-12 数据库的基本操作和存储引擎
			一. 储备知识 数据库服务器:一台高性能计算机 数据库管理系统:mysql(mssql等),是一个软件 数据库:db1(student_db),是一个文件夹 表:studen_info 是一个文件 记 ... 
- 关于手机端适配的问题(rem,页面缩放)
			关于手机端适配的问题(rem,页面缩放) 96 进击的小前端 关注 2018.02.02 13:57 字数 320 阅读 19评论 0喜欢 0 相信很多和会和我碰到一样的情况,就是你用rem去写移动端 ... 
- 【apache2】AH00543: httpd: bad user name apache
			当启动 apache 时,出现一下异常:AH00543: httpd: bad user name daemon 解决方法: #groupadd daemon ... 
- Appscanner实验还原code2
			import _pickle as pickle from sklearn import svm, ensemble import random from sklearn.metrics import ... 
