AtcoderGrandContest 005 F. Many Easy Problems
$ >AtcoderGrandContest \space 005 F. \ Many\ Easy\ Problems<$
题目大意 :
有一棵大小为 \(n\) 的树,对于每一个 \(k \in[1,n]\) ,求出在所有在树中选 \(k\) 个点的方案对应的包含这 \(k\) 个点的最小联通块大小之和\(1 \leq n \leq 2 \times 10^5\)
解题思路 :
容易发现,对于一组选取方案,包含它的最小联通块是唯一的,不妨考虑每一个点对这个联通块的贡献.
观察发现,一个点如果在一个最小联通块中,当且仅当有两个选取点的简单路径经过它
那么点 \(u\) 对 \(k\) 个点的贡献就是 \(C_n^k -\sum_{v} C_{sz[v]}^k-C_{n-sz[u]}^k\)
观察发现这个式子只和 \(sz\) 有关,不妨设 \(tot[i]\) 表示 \(sz[u]=i\) 的点的数量
考虑除根以外的每一个点只会在其父亲计算的时候被减去一个 \(C_{sz[u]}^k\) ,同时每一种 \(sz[u]\) 都会在计算大小为 \(n-sz[u]\) 的子树的时候被减去一次
所以 \(C_{sz[u]}^k\) 的被计算次数是 \(tot[sz[u]] + tot[n-sz[u]]\)
那么最终答案的式子就是 \(Ans_j =n \times C_n^j -\sum_{i=1}^n (tot[i]+tot[n-i])\times C_i^j\)
设 \(inv[i]\) 表示 \(i!\) 关于 \(Mod\) 的逆元,将后面的组合数拆开来可以得到
\(Ans_j =n \times C_n^j -\sum_{i=1}^n (tot[i]+tot[n-i])\times i! \times inv[j] \times inv[i-j]\)
设 \(A[i] = (tot[i]+tot[n-i])\times i!\) ,则 \(Ans_j = n \times C_n^j \times inv[j] - \sum_{i=1}^nA[i]\times inv[i-j]\), 后者 \(NTT\) 进行计算即可
/*program by mangoyang*/
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#include<bits/stdc++.h>
#define inf (0x7f7f7f7f)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
int f = 0, ch = 0; x = 0;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
if(f) x = -x;
}
#define int ll
const int N = 1605005, L = 200005, P = 924844033, G = 5;
vector<int> g[N];
int inv[N], iv[N], s[N], f[N], tot[N], sz[N], js[N], n;
inline int Pow(int a, int b){
int ans = 1;
for(; b; b >>= 1, a = a * a % P)
if(b & 1) ans = ans * a % P;
return ans;
}
namespace NTT{
int rev[N];
inline int Getrev(int ned){
int lg = 0, len = 1;
for(; len <= ned; len <<= 1, lg++);
for(int i = 0; i < len; i++)
rev[i] = (rev[i>>1] >> 1) | ((i & 1) << (lg - 1));
return len;
}
inline void DFT(int *A, int len, int type){
for(int i = 0; i < len; i++) if(i < rev[i]) swap(A[i], A[rev[i]]);
for(int k = 2; k <= len; k <<= 1){
int w = Pow(G, (P - 1) / k); if(type == -1) w = Pow(w, P - 2);
for(int i = 0; i < len; i += k){
int now = 1;
for(int j = i; j < i + (k >> 1); j++, (now *= w) %= P){
int x = A[j], y = (now * A[j+(k>>1)]) % P;
A[j] = (x + y) % P, A[j+(k>>1)] = (x - y + P) % P;
}
}
}
if(type == -1){
int now = Pow(len, P - 2);
for(int i = 0; i < len; i++) (A[i] *= now) %= P;
}
}
inline void Times(int *A, int *B, int lena, int lenb){
int len = Getrev(lena + lenb + 1);
DFT(A, len, 1), DFT(B, len, 1);
for(int i = 0; i < len; i++) A[i] = A[i] * B[i] % P;
DFT(A, len, -1);
}
}
inline void dfs(int u, int fa){
sz[u] = 1, f[u] = fa;
for(int i = 0; i < g[u].size(); i++)
if(g[u][i] != fa) dfs(g[u][i], u), sz[u] += sz[g[u][i]];
}
inline int C(int x, int y){
return js[x] * inv[y] % P * inv[x-y] % P;
}
signed main(){
read(n), js[0] = 1, inv[0] = iv[L] = 1;
for(int i = 1; i <= n; i++){
js[i] = js[i-1] * i % P;
iv[L-i] = inv[i] = Pow(js[i], P - 2);
}
for(int i = 1, x, y; i < n; i++){
read(x), read(y);
g[x].push_back(y), g[y].push_back(x);
}
dfs(1, 0);
for(int i = 2; i <= n; i++) tot[sz[i]]++;
for(int i = 1; i <= n; i++)
s[L+i] = (tot[i] + tot[n-i]) * js[i] % P;
NTT::Times(s, iv, L + n + 1, L + n + 1);
for(int i = 1; i <= n; i++){
int A = n * C(n, i) % P;
int B = inv[i] * s[2*L+i] % P;
printf("%lld\n", ((A - B) % P + P) % P);
}
return 0;
}
AtcoderGrandContest 005 F. Many Easy Problems的更多相关文章
- [题解] Atcoder AGC 005 F Many Easy Problems NTT,组合数学
题目 观察当k固定时答案是什么.先假设每个节点对答案的贡献都是\(\binom{n}{k}\),然后再减掉某个点没有贡献的选点方案数.对于一个节点i,它没有贡献的方案数显然就是所有k个节点都选在i连出 ...
- 【AtCoder】AGC005 F - Many Easy Problems 排列组合+NTT
[题目]F - Many Easy Problems [题意]给定n个点的树,定义S为大小为k的点集,则f(S)为最小的包含点集S的连通块大小,求k=1~n时的所有点集f(S)的和取模92484403 ...
- 解题: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 ...
- 【CodeForces】913 D. Too Easy Problems
[题目]D. Too Easy Problems [题意]给定n个问题和总时限T,每个问题给定时间ti和限制ai,当解决的问题数k<=ai时问题有效,求在时限T内选择一些问题解决的最大有效问题数 ...
- 【AGC005 F】Many Easy Problems
神他吗一天考一道码农题两道 FFT(其实还是我推式子一窍不通) 题意 给你一棵 \(n\) 个点的树,再给你一个常数 \(k\). 设 \(S\) 为树上某些点的集合,定义 \(f(S)\) 为最小的 ...
- 【AGC 005F】Many Easy Problems
Description One day, Takahashi was given the following problem from Aoki: You are given a tree with ...
- AtCoder - 2064 Many Easy Problems
Problem Statement One day, Takahashi was given the following problem from Aoki: You are given a tree ...
- Codeforces B. Too Easy Problems
题目描述: time limit per test 2 seconds memory limit per test 256 megabytes input standard input output ...
随机推荐
- 关于jQuery UI 使用心得及技巧
1 jQuery UI 有时你仅仅是为了实现一个渐变的动画效果而不得不把javascrip 重新学习一遍然后书写大量代码.直到jQuery的出现,让开发人员从一大堆繁琐的js代码中解脱,取而代之几行j ...
- TreeSet的特性
TreeSet在Set的元素不重复的基础之上引入排序的概念,其中对自身拥有Comparable的元素,可以直接进行排序,比如字符串,按照字母的自然顺序排序,此处说下对于自定义对象排序的方式. 1.存储 ...
- 【BZOJ4870】组合数问题(计数DP,快速幂)
题意: 1 ≤ n ≤ 10^9, 0 ≤ r < k ≤ 50, 2 ≤ p ≤ 2^30 − 1 思路:From http://blog.csdn.net/qq_33229466/artic ...
- [BZOJ 3039&洛谷P4147]玉蟾宫 题解(单调栈)
[BZOJ 3039&洛谷P4147]玉蟾宫 Description 有一天,小猫rainbow和freda来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地. ...
- 【leetcode 简单】第四十一题 Excel表列序号
给定一个Excel表格中的列名称,返回其相应的列序号. 例如, A -> 1 B -> 2 C -> 3 ... Z -> 26 AA -> 27 AB -> 28 ...
- 2017ACM暑期多校联合训练 - Team 8 1006 HDU 6138 Fleet of the Eternal Throne (字符串处理 AC自动机)
题目链接 Problem Description The Eternal Fleet was built many centuries ago before the time of Valkorion ...
- vue去除地址栏上的'#'号
const router = new VueRouter({ routes:[], mode :"history"//除去#号 }
- 按键精灵MySql数据库操作
查询 MySql服务器地址="192.168.1.166" 用户名 = "root" 密码 = " 数据库名="bookshop" ...
- notepad++突然崩溃,保存的文件没了怎么办
在C:\Users\你当前用户的用户名\AppData\Roaming\Notepad++\backup 有备份
- ueditor和thinkphp框架整合修改版
基于tp官网上的一篇文章修改的 因为tp中所有目录其实都是性对于入口文件的 在原来的基础上略做修改后 已经做到 无论项目放在www下的任何位置 图片在编辑器中回填后都能正常显示! http://fi ...