Gym102538A Airplane Cliques
时间:2020-04-12
本文章向大家介绍Gym102538A Airplane Cliques,主要包括Gym102538A Airplane Cliques使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
Link
我们用\(T\)来表示题目给出的树,用\(S\)来表示枚举的点集。
不难发现\(G=T^x\)是一个弦图。(\(T^x\)指将\(T\)中距离不超过\(x\)的点两两连边得到的图)
然后我们任意固定一个点为根,然后将所有点按深度降序排序。事实上这个序列恰好是\(G\)的一个完美消除序列。
设\(a_u\)表示在完美消除序列中在\(u\)后面的且和\(u\)相邻的点的个数,这可以通过点分治等途径求出。
固定\(|S|=k\),然后枚举\(S\)中在完美消除序列中最靠前的点\(u\),那么选择其它\(k-1\)个点的方案数就是\({a_u\choose k-1}\)。
设\(f_i\)为\(|S|=i+1\)的个数,那么有\(f_i=\sum\limits_{j=1}^n{a_j\choose i}\)。
设\(t_x=\sum\limits_{i=1}^n[a_u=x]\),那么\(f_i=\sum\limits_{j=i}^{n-1}t_j{j\choose i}\)。
利用NTT即可求出\(f\)。
#include<cctype>
#include<cstdio>
#include<vector>
#include<cstring>
#include<numeric>
#include<algorithm>
const int N=1<<20|1,P=998244353;
int read(){int x=0,c=getchar();while(isspace(c))c=getchar();while(isdigit(c))(x*=10)+=c&15,c=getchar();return x;}
void inc(int&a,int b){a+=b-P,a+=a>>31&P;}
void dec(int&a,int b){a-=b,a+=a>>31&P;}
int mul(int a,int b){return 1ll*a*b%P;}
int pow(int a,int k){int r=1;for(;k;k>>=1,a=mul(a,a))if(k&1)r=mul(a,r);return r;}
int n,x,lim,cnt[N],dep[N],pre[N],id[N],fac[N],ifac[N],w[N],rev[N],f[N],g[N];std::vector<int>e[N];
namespace Divide_and_Conquer
{
int root,mn,m1,m2,vis[N],size[N],s1[N],s2[N];
void dfs(int u){size[u]=vis[u]=1;for(int v:e[u])if(!vis[v])dfs(v),size[u]+=size[v];vis[u]=0;}
void find(int u,int s){int mx=0;vis[u]=1;for(int v:e[u])if(!vis[v])find(v,s),mx=std::max(mx,size[v]);if(vis[u]=0,(mx=std::max(mx,s-size[u]))<mn)root=u,mn=mx;}
int get(int u,int d,int*s){int mx=d;if(vis[u]=1,u<=n)++s[d];for(int v:e[u])if(!vis[v])mx=std::max(mx,get(v,d+1,s));return vis[u]=0,mx;}
void calc(int u,int d){if(d>x) return;cnt[u]+=s1[std::min(x-d,m1)]-s2[std::min(x-d,m2)],vis[u]=1;for(int v:e[u])if(!vis[v])calc(v,d+1);vis[u]=0;}
void divide(int u)
{
mn=1e9,dfs(u),find(u,size[u]),u=root,m1=get(u,0,s1),std::partial_sum(s1,s1+m1+1,s1),cnt[u]+=s1[std::min(m1,x)],vis[u]=1;
for(int v:e[u]) if(!vis[v]) m2=get(v,1,s2),std::partial_sum(s2,s2+m2+1,s2),calc(v,1),memset(s2,0,(m2+1)<<2);
memset(s1,0,(m1+1)<<2);
for(int v:e[u]) if(!vis[v]) divide(v);
}
}
void dfs(int u,int fa)
{
static int stk[N],top;
dep[u]=dep[fa]+1,stk[++top]=u,pre[u]=stk[std::max(1,top-x)];
for(int v:e[u]) if(v^fa) dfs(v,u);
--top;
}
void init(int n)
{
static int p=(lim=1<<(33-__builtin_clz(n)))/2,g=pow(3,(P-1)/lim);
w[p]=1,fac[0]=1;
for(int i=1;i<lim;++i) rev[i]=(rev[i>>1]>>1)|(i&1? p:0);
for(int i=p+1;i<lim;++i) w[i]=mul(w[i-1],g);
for(int i=p-1;i;--i) w[i]=w[i<<1];
for(int i=1;i<=n;++i) fac[i]=mul(fac[i-1],i);
ifac[n]=pow(fac[n],P-2);
for(int i=n;i;--i) ifac[i-1]=mul(ifac[i],i);
}
void NTT(int*a,int f)
{
if(!~f) std::reverse(a+1,a+lim);
for(int i=1;i<lim;++i) if(i<rev[i]) std::swap(a[i],a[rev[i]]);
for(int i=1;i<lim;i<<=1) for(int j=0,d=i<<1;j<lim;j+=d) for(int k=0,x;k<i;++k) x=mul(a[i+j+k],w[i+k]),dec(a[i+j+k]=a[j+k],x),inc(a[j+k],x);
if(!~f) for(int i=0,x=P-(P-1)/lim;i<lim;++i) a[i]=mul(a[i],x);
}
int main()
{
n=read(),x=read(),init(n-1),memcpy(g,ifac,n<<2),std::reverse(g,g+n);
for(int i=1,u,v;i<n;++i) u=read(),v=read(),e[u].push_back(n+i),e[v].push_back(n+i),e[n+i].push_back(u),e[n+i].push_back(v);
Divide_and_Conquer::divide(1),dfs(1,0),std::iota(id+1,id+n+1,1),std::sort(id+1,id+n+1,[](int i,int j){return dep[i]>dep[j];});
for(int i=1;i<=n;++i) ++f[--cnt[pre[i]]];
for(int i=0;i<n;++i) f[i]=mul(f[i],fac[i]);
NTT(f,1),NTT(g,1);
for(int i=0;i<lim;++i) f[i]=mul(f[i],g[i]);
NTT(f,-1);
for(int i=0;i<n;++i) printf("%d ",mul(ifac[i],f[i+n-1]));
}
原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12687717.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 哈?命令注入外带数据的姿势还可以这么骚?
- 记一次曲折的RCE挖掘
- pytest文档49-命令行参数--tb的使用
- pytest文档50-命令行参数--durations统计用例运行时间
- pytest文档51-内置fixture之cache使用
- pytest文档53-命令行实时输出错误信息(pytest-instafail)
- pytest文档52-命令行参数--setup-show查看fixture的执行过程
- pytest文档54-Hooks函数terminal打印测试结果(pytest_report_teststatus)
- SAS-免费的描述性统计程序自动化创建
- Godot游戏开发实践之四:搬运Unity的Pluggable AI教程
- TypeScript 4.1 新特性:字符串模板类型,Vuex 终于有救了?
- 使用 Node.js 定制你的技术雷达:上篇
- 使用 Node.js 定制你的技术雷达:中篇
- 大点干!早点散----------Redis从入门到精通!!!
- Python入门摘要