题面

两道题比较像,放在一起写了,后者可以看成前者的加强版

(sto ztb orz)


先看AT那道题

考虑计算每个点的贡献,用容斥计算:每个点没有贡献当且仅当选的所有点都在以他为根时的一个子节点的子树里。所以对于每个点i,其贡献为$C_n^k-\sum_{v∈son_i}C_{size[v]}^k$,这样我们就得到了一个$O(n^2)$的算法

考虑优化,来列出来总的式子

$ans=n*C_n^k-\sum\limits_{i=1}^n\sum_{v∈son_i}C_{size[v]}^k$

前面的随便算,先不管了。考虑后面,用卷积优化时常见的套路,开个桶$bkt[i]$统计size等于i的情况的个数

$ans'=\sum\limits_{i=1}^n bkt[i] C_{i}^k$

组合数,拆除!

$ans'=\sum\limits_{i=1}^n bkt[i]*i! \frac{1}{k!(i-k)!}$

$k!*ans'=\sum\limits_{i=1}^n bkt[i]*i! \frac{1}{(i-k)!}$

上NTT即可


再来看ER那道题

我们仍然考虑贡献,点i产生贡献有两种方式:

1.作为被选出的点,有$C_{n-1}^{k-1}$种选的方法

2.作为构建虚树时被捉出来的LCA

显然重点在第二种上,我们仍然使用容斥来计算......

额式子太长了,不想写了,搬题解了

来啊,NTT啊(


Code:

Many Easy Problems↓

 #include<cmath>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=,mod=;
int n,nm,t1,t2,cnt,G,Gi;
int p[N],noww[N],goal[N],siz[N];
int rev[N],fac[N],inv[N],a[N],b[N],pw[][];
void Read(int &x)
{
x=; char ch=getchar();
while(!isdigit(ch))
ch=getchar();
while(isdigit(ch))
x=(x<<)+(x<<)+(ch^),ch=getchar();
}
int Addit(int x,int y)
{
x+=y;
if(x>=mod) x-=mod;
return x;
}
int Qpow(int x,int k)
{
if(k==) return x;
int tmp=Qpow(x,k/);
return k%?1ll*tmp*tmp%mod*x%mod:1ll*tmp*tmp%mod;
}
void Link(int f,int t)
{
noww[++cnt]=p[f];
goal[cnt]=t,p[f]=cnt;
noww[++cnt]=p[t];
goal[cnt]=f,p[t]=cnt;
}
int C(int a,int b)
{
return 1ll*fac[a]*inv[b]%mod*inv[a-b]%mod;
}
void DFS(int nde,int fth)
{
siz[nde]=;
for(int i=p[nde];i;i=noww[i])
if(goal[i]!=fth)
{
DFS(goal[i],nde);
a[siz[goal[i]]]++;
siz[nde]+=siz[goal[i]];
}
a[n-siz[nde]]++;
}
void Pre()
{
fac[]=inv[]=;
for(int i=;i<=n;i++) fac[i]=1ll*fac[i-]*i%mod;
inv[n]=Qpow(fac[n],mod-);
for(int i=n-;i;i--) inv[i]=1ll*inv[i+]*(i+)%mod;
nm=*n,n=; while(n<=nm) n<<=; G=,Gi=Qpow(G,mod-),nm>>=;
for(int i=;i<=n;i++) rev[i]=(rev[i>>]>>)+(i&)*(n>>);
for(int i=;i<=;i++)
{
pw[i][]=Qpow(G,(mod-)/(<<i));
pw[i][]=Qpow(Gi,(mod-)/(<<i));
}
for(int i=;i<=nm;i++) a[i]=1ll*a[i]*fac[i]%mod,b[i]=inv[nm-i];
}
void Trans(int *arr,int len,int typ)
{
register int i,j,k;
for(i=;i<len;i++)
if(rev[i]>i) swap(arr[rev[i]],arr[i]);
for(i=;i<=len;i<<=)
{
int lth=i>>,ort=pw[(int)log2(i)][typ==-];
for(j=;j<len;j+=i)
{
int ori=,tmp;
for(k=j;k<j+lth;k++,ori=1ll*ori*ort%mod)
{
tmp=1ll*ori*arr[k+lth]%mod;
arr[k+lth]=(arr[k]-tmp+mod)%mod;
arr[k]=(arr[k]+tmp)%mod;
}
}
}
if(typ==-)
{
int Ni=Qpow(len,mod-);
for(i=;i<=len;i++)
arr[i]=1ll*arr[i]*Ni%mod;
}
}
int main()
{
Read(n);
for(int i=;i<n;i++)
Read(t1),Read(t2),Link(t1,t2);
DFS(,),Pre();
Trans(a,n,),Trans(b,n,);
for(int i=;i<n;i++) a[i]=1ll*a[i]*b[i]%mod;
Trans(a,n,-);
for(int i=;i<=nm;i++)
{
int ans=1ll*C(nm,i)*nm%mod-1ll*a[nm+i]*inv[i]%mod;
printf("%d\n",Addit(ans,mod));
}
return ;
}

两开花↓

 #include<cmath>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=,mod=;
int n,m,nm,t1,t2,cnt,G,Gi;
int p[N],noww[N],goal[N],siz[N];
int rev[N],fac[N],inv[N],a[N],b[N],pw[][];
void Read(int &x)
{
x=; char ch=getchar();
while(!isdigit(ch))
ch=getchar();
while(isdigit(ch))
x=(x<<)+(x<<)+(ch^),ch=getchar();
}
int Addit(int x,int y)
{
x+=y;
if(x>=mod) x-=mod;
return x;
}
int Qpow(int x,int k)
{
if(k==) return x;
int tmp=Qpow(x,k/);
return k%?1ll*tmp*tmp%mod*x%mod:1ll*tmp*tmp%mod;
}
void Link(int f,int t)
{
noww[++cnt]=p[f];
goal[cnt]=t,p[f]=cnt;
noww[++cnt]=p[t];
goal[cnt]=f,p[t]=cnt;
}
int C(int a,int b)
{
return 1ll*fac[a]*inv[b]%mod*inv[a-b]%mod;
}
void DFS(int nde,int fth)
{
siz[nde]=;
for(int i=p[nde];i;i=noww[i])
if(goal[i]!=fth)
{
DFS(goal[i],nde);
siz[nde]+=siz[goal[i]];
}
a[n-]++; int tmp=;
for(int i=p[nde];i;tmp++,i=noww[i])
if(goal[i]!=fth) a[n-siz[nde]+siz[goal[i]]]--;
a[n-siz[nde]]+=tmp--(nde!=);
}
void Pre()
{
fac[]=inv[]=;
for(int i=;i<=n;i++) fac[i]=1ll*fac[i-]*i%mod;
inv[n]=Qpow(fac[n],mod-);
for(int i=n-;i;i--) inv[i]=1ll*inv[i+]*(i+)%mod;
nm=*n,n=; while(n<=nm) n<<=; G=,Gi=Qpow(G,mod-),nm>>=;
for(int i=;i<=n;i++) rev[i]=(rev[i>>]>>)+(i&)*(n>>);
for(int i=;i<=;i++)
{
pw[i][]=Qpow(G,(mod-)/(<<i));
pw[i][]=Qpow(Gi,(mod-)/(<<i));
}
for(int i=;i<=nm;i++) a[i]=1ll*Addit(a[i],mod)*fac[i]%mod,b[i]=inv[nm-i];
}
void Trans(int *arr,int len,int typ)
{
register int i,j,k;
for(i=;i<len;i++)
if(rev[i]>i) swap(arr[rev[i]],arr[i]);
for(i=;i<=len;i<<=)
{
int lth=i>>,ort=pw[(int)log2(i)][typ==-];
for(j=;j<len;j+=i)
{
int ori=,tmp;
for(k=j;k<j+lth;k++,ori=1ll*ori*ort%mod)
{
tmp=1ll*ori*arr[k+lth]%mod;
arr[k+lth]=(arr[k]-tmp+mod)%mod;
arr[k]=(arr[k]+tmp)%mod;
}
}
}
if(typ==-)
{
int Ni=Qpow(len,mod-);
for(i=;i<=len;i++)
arr[i]=1ll*arr[i]*Ni%mod;
}
}
int main()
{
Read(n),Read(m);
for(int i=;i<n;i++)
Read(t1),Read(t2),Link(t1,t2);
DFS(,),Pre();
Trans(a,n,),Trans(b,n,);
for(int i=;i<n;i++) a[i]=1ll*a[i]*b[i]%mod;
Trans(a,n,-);
for(int i=;i<=m;i++)
{
int ans=Addit(1ll*a[nm+i]*inv[i]%mod,1ll*C(nm-,i-)*nm%mod);
printf("%lld\n",1ll*ans*Qpow(C(nm,i),mod-)%mod);
}
return ;
}

解题:AT2064 Many Easy Problems&EXNR #1 T3 两开花的更多相关文章

  1. AtcoderGrandContest 005 F. Many Easy Problems

    $ >AtcoderGrandContest \space 005 F.  Many Easy Problems<$ 题目大意 : 有一棵大小为 \(n\) 的树,对于每一个 \(k \i ...

  2. Codeforces 913D - Too Easy Problems

    913D - Too Easy Problems 思路:二分check k 代码: #include<bits/stdc++.h> using namespace std; #define ...

  3. 【AtCoder】AGC005 F - Many Easy Problems 排列组合+NTT

    [题目]F - Many Easy Problems [题意]给定n个点的树,定义S为大小为k的点集,则f(S)为最小的包含点集S的连通块大小,求k=1~n时的所有点集f(S)的和取模92484403 ...

  4. 【CodeForces】913 D. Too Easy Problems

    [题目]D. Too Easy Problems [题意]给定n个问题和总时限T,每个问题给定时间ti和限制ai,当解决的问题数k<=ai时问题有效,求在时限T内选择一些问题解决的最大有效问题数 ...

  5. [AT2064] [agc005_f] Many Easy Problems

    题目链接 AtCoder:https://agc005.contest.atcoder.jp/tasks/agc005_f 洛谷:https://www.luogu.org/problemnew/sh ...

  6. Codeforces B. Too Easy Problems

    题目描述: time limit per test 2 seconds memory limit per test 256 megabytes input standard input output ...

  7. 【AGC 005F】Many Easy Problems

    Description One day, Takahashi was given the following problem from Aoki: You are given a tree with ...

  8. AtCoder - 2064 Many Easy Problems

    Problem Statement One day, Takahashi was given the following problem from Aoki: You are given a tree ...

  9. 【AGC005F】Many Easy Problems FFT 容斥原理

    题目大意 给你一棵树,有\(n\)个点.还给你了一个整数\(k\). 设\(S\)为树上某些点的集合,定义\(f(S)\)为最小的包含\(S\)的联通子图的大小. \(n\)个点选\(k\)个点一共有 ...

随机推荐

  1. kettle学习笔记(十)——数据检验、统计、分区与JS脚本

    一.概述 数据剖析和数据检验: 用于数据的检查.清洗 . 统计步骤: 提供数据采样和统计的功能 分区: 根据数据里某个字段的值,拆分成多个数据块.输出到不同的库表和文件中. 脚本: Javascrip ...

  2. 2017-2018-2 20155224『网络对抗技术』Exp6:信息搜集与漏洞扫描

    实践内容 各种搜索技巧的应用 DNS IP注册信息的查询 基本的扫描技术:主机发现.端口扫描.OS及服务版本探测.具体服务的查点 漏洞扫描:会扫,会看报告,会查漏洞说明,会修补漏洞 基本问题回答 哪些 ...

  3. Asp.Net StateServer实现共同域名下Session共享

    概述 在实验的时候,参照了多方的信息,确实成功了,这里简单记录一下. 我们知道,在Asp.Net的Web.Config文件中,System.Web节点下,有个sessionState节点,它说明了应用 ...

  4. python 回溯法 子集树模板 系列 —— 1、8 皇后问题

    问题 8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. 分析 为了简化问题,考虑到8个皇后不同行,则每一行放置一个皇后,每一行的 ...

  5. TMS320VC5509的MCBSP配置成SPI模式通信

    1. 首先是把MCBSP的配置 其次是时钟停止模式的配置,关闭大同小异 SPI有4中模式,怎么根据上面的寄存器选择哪种模式?下面展示了其中两种,CLKXP=1的时候有另外两种,暂时不整出来了 2. 代 ...

  6. vue 监听页面宽度变化 和 键盘事件

    vue 监听页面窗口大小 export default { name: 'Full', components: { Header, Siderbar }, data () { return { scr ...

  7. SpringBoot日记——信息修改PUT篇

    我们常用的功能,除了post和get,还有put和delete,这篇文章就介绍一下这个put的基本用法. 页面跳转和回显 1. 首先,我们之前的页面已经将添加和修改的按钮都做好了,那么如何实现这些按钮 ...

  8. 阿里云rds 备份和还原

    阿里云rds 备份和还原 转发:https://www.cnblogs.com/lin1/p/8617764.html 转发:https://help.aliyun.com/knowledge_det ...

  9. Unity3D Shader 学习笔记(一):初识Shader

    第一节:图形处理器简史 GPU发展简史 GPU英文全称Graphic Procssing Unit. T&L变换和光照流水线 可编程GPU GPU的优点和缺点 第二节:Unity Shader ...

  10. Google Kickstart Round.B C. Diverse Subarray

    这题又是万恶的线段树 maxx[j]存储的是 l = xxx, r = j的时候的答案 我们会让 l 从 1到n 的遍历中,查询线段树的[l, n]中最大的答案 因为query的下界是n,所以单次查询 ...