题面

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

(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. 20155210 EXP6 信息搜集与漏洞扫描

    20155210 EXP6 信息搜集与漏洞扫描 信息搜集 外围信息搜集 通过DNS和IP挖掘目标网站的信息 whois 域名注册信息查询 我们通过输入whois qq.com可查询到3R注册信息,包括 ...

  2. 20155302《网络对抗》Exp7 网络欺诈防范

    20155302<网络对抗>Exp7 网络欺诈防范 实验内容 (1)简单应用SET工具建立冒名网站 (1分) (2)ettercap DNS spoof (1分) (3)结合应用两种技术, ...

  3. tf tensor 输出

    在学习TensorFlow的过程中,我们需要知道某个tensor的值是什么,这个很重要,尤其是在debug的时候.也许你会说,这个很容易啊,直接print就可以了.其实不然,print只能打印输出sh ...

  4. Android开发——进程间通信之Bundle和文件

    0.  前言 不论是Android还是其他操作系统,都会有自己的IPC机制,所谓IPC(Inter-Process Communication)即进程间通信.首先线程和进程是很不同的概念,线程是CPU ...

  5. 【干货】YUM安装PHP 7版本后,增加phalcon框架的报错解决

    目录 1.yum安装php 7.x版本,此处部署7.3版本 2.安装phalcon框架 2.1.PHP版本依赖关系 2.2.编译phalcon扩展模块 2.3.增加扩展文件 3.部署phalcon遇到 ...

  6. PHP调用WCF提供的方法

    一.准备工作 1.安装wampserver:过程略 2.配置wampserver: 2.1打开php.ini文件,去掉 ;extension=php_soap.dll 这里那个分号. 也有说把这个 ; ...

  7. PowerBI开发 第十二篇:钻取

    钻取是指沿着层次结构(维度的层次)查看数据,钻取可以变换分析数据的粒度.钻取分为下钻(Drill-down)和上钻(Drill-up),上钻是沿着数据的维度结构向上聚合数据,在更大的粒度上查看数据的统 ...

  8. C语言与数据库操作入门(Win版)

    C语言与数据库操作入门(Win版) 2017年12月10日 17:30:17 阅读数:1387 数据库,DataBase,学C语言的是不是想说,很想爱她却并不容易呢?不用着急,C语言也可以操作数据库的 ...

  9. install opencv 2.4.10 with issue :"nvcc fatal : Unsupported gpu architecture 'compute_11'"

    issue: nvcc fatal   : Unsupported gpu architecture 'compute_11'CMake Error at cuda_compile_generated ...

  10. Linux shell (6)

    1.linux shell函数: 将一组命令集或语句形成一个可用的块,这些语句块成为函数. 2.shell 函数的组成:  函数名:函数的名字,注意一个脚本中函数名要唯一,否则会引起调用函数紊乱  函 ...