题面

传送门

题解

妈呀调了我整整一天……

题解太长了不写了可以去看\(shadowice\)巨巨的

//minamoto
#include<bits/stdc++.h>
#define R register
#define ull unsigned int
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=T->head[u],v=T->e[i].v;i;i=T->e[i].nx,v=T->e[i].v)
#define gg(u) for(int i=u,v=lg[i&-i];i;i-=i&-i,v=lg[i&-i])
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
R int res,f=1;R char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
return res*f;
}
const int N=5005,M=1e7+5,P=998244353,inv2=499122177;
inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R int y){
R int res=1;
for(;y;y>>=1,x=mul(x,x))if(y&1)res=mul(res,x);
return res;
}
const ull base1=998,base2=244;
int n,k,ans;
int deg[M],s[M],C[N][15],fac[15];
struct Gr{
struct eg{int v,nx;}e[M];int head[M],tot,n;
inline void Add(R int u,R int v){e[++tot]={v,head[u]},head[u]=tot;}
inline void Pre(R int x){n=x,tot=1;fp(i,1,n)head[i]=0;}
int calc(){
int res=0;fp(i,1,n)deg[i]=s[i]=0;
fp(i,2,tot)++deg[e[i].v];
fp(u,1,n)for(int i=head[u];i;i=e[i].nx)s[u]+=deg[u]+deg[e[i].v]-3;
fp(i,1,n)res=add(res,mul(s[i],s[i]));
res=mul(res,inv2);
for(int i=2;i<=tot;i+=2){
int d=deg[e[i].v]+deg[e[i^1].v]-2;
res=(res+P-(d-1)*(d-1))%P;
res=(res+1ll*d*(d-1)*(d-2)/2)%P;
}
return res;
}
}pool[3],*T,*E[2];
int lg[N],pc[N];
struct Tr{
ull f[15],q[15],mdzz;int siz[15],jc[15],to[15],n;
inline void Add(R int u,R int v){to[u]|=(1<<v);}
inline void clr(){fp(i,0,n-1)to[i]=0;n=0;}
void dfs(int u){
siz[u]=1;
gg(to[u])dfs(v),siz[u]+=siz[v];
int t=0;gg(to[u])q[++t]=f[v];
sort(q+1,q+1+t),q[t+1]=q[t]+1,q[0]=q[1]+1,f[u]=siz[u],jc[u]=1;
fp(i,1,t)f[u]=f[u]*base1+q[i];
for(int i=1,s=1,cnt=1;i<=t+1;++i)
q[i]==q[i-1]?(++cnt,s=mul(s,cnt)):(jc[u]=mul(jc[u],s),s=cnt=1);
jc[u]=ksm(jc[u],P-2),f[u]*=base2*siz[u];
}
inline void Pre(){dfs(0),mdzz=f[0];}
int sz[15],vis;
void calc(int u,int S){
sz[u]=1,vis|=(1<<u);
gg(to[u]&S)calc(v,S),sz[u]+=sz[v];
int t=0;gg(to[u]&S)q[++t]=f[v];
sort(q+1,q+1+t),f[u]=sz[u];
fp(i,1,t)f[u]=f[u]*base1+q[i];
f[u]*=base2*sz[u];
}
int ck(int S){
int mx=lg[S&-S];
fp(i,0,n-1)((S>>i&1)&&siz[i]>siz[mx])?mx=i:0;
vis=0,calc(mx,S);return vis==S?mx:-1;
}
}qwq,*ntr;
void Line(Gr *a,Gr *b){
b->Pre((a->tot-1)>>1);
fp(u,1,a->n)for(int i=a->head[u];i;i=a->e[i].nx)for(int j=a->e[i].nx;j;j=a->e[j].nx)
b->Add(i>>1,j>>1),b->Add(j>>1,i>>1);
}
map<ull,int>mp;
int calcnode(int k){
int nw=0,pw=1;k-=4;
while(k--)Line(E[nw],E[pw]),nw^=1,pw^=1;
return E[nw]->calc();
}
int calc(){
ntr->Pre(),E[0]->Pre(ntr->n);
fp(u,0,ntr->n-1)gg(ntr->to[u])E[0]->Add(u+1,v+1),E[0]->Add(v+1,u+1);
int res=calcnode(k);
fp(i,1,(1<<ntr->n)-2){
int p=ntr->ck(i);
((~p)&&mp.find(ntr->f[p])!=mp.end())?res=dec(res,mp[ntr->f[p]]):0;
}
return mp[ntr->mdzz]=res;
}
int g[N],las[15],leaf[15],f[N][15];bool L[15];
void dfs(int u,int fa){
int sz=0;
go(u)v!=fa?(dfs(v,u),++sz):0;
fp(i,0,ntr->n-1){
if(L[i])continue;
if(sz<pc[ntr->to[i]]){f[u][i]=0;continue;}
for(int j=ntr->to[i];j;j=(j-1)&ntr->to[i])g[j]=0;
g[0]=1;
for(int j=T->head[u],v=T->e[j].v;j;j=T->e[j].nx,v=T->e[j].v)if(v!=fa)
for(int k=ntr->to[i];k;k=(k-1)&ntr->to[i])
for(int p=k;p;p-=p&-p)
g[k]=add(g[k],1ll*g[k^(p&-p)]*f[v][lg[p&-p]]%P);
f[u][i]=1ll*g[ntr->to[i]]*ntr->jc[i]%P*C[sz-pc[ntr->to[i]]][leaf[i]]%P*fac[leaf[i]]%P;
}
}
int calctimes(){
fp(i,0,ntr->n-1)las[i]=ntr->to[i],leaf[i]=L[i]=0;
fp(u,0,ntr->n-1)gg(ntr->to[u])ntr->siz[v]==1?(++leaf[u],ntr->to[u]^=(1<<v)):0;
fp(i,0,ntr->n-1)ntr->siz[i]==1?L[i]=true:0;
dfs(1,0);
fp(u,0,ntr->n-1)ntr->to[u]=las[u];
int res=0;
fp(i,1,n)res=add(res,f[i][0]);
return res;
}
int fa[25];
int st[N<<1],top;set<ull>vis;
void solve(int x,int c,int sp,int lim){
if(x==(lim-1)*2+1){
int now=0,tot=0;ntr->clr();
fp(i,1,x-1)st[i]==1?(ntr->to[now]|=(1<<(++tot)),fa[tot]=now,now=tot):now=fa[now];
ntr->n=lim,ntr->Pre();
if(vis.find(ntr->mdzz)!=vis.end())return;
vis.insert(ntr->mdzz);
ans=add(ans,1ll*calctimes()*calc()%P);
return;
}
if(c)st[x]=-1,solve(x+1,c-1,sp,lim);
if(sp<lim-1)st[x]=1,solve(x+1,c+1,sp+1,lim);
}
void spj(){
switch(k){
case 1:printf("%d\n",n-1);break;
case 2:{
fp(i,1,n)ans=add(ans,1ll*deg[i]*(deg[i]-1)>>1);
printf("%d\n",ans);
break;
}
case 3:{
for(int i=2;i<T->tot;i+=2){
int d=deg[T->e[i].v]+deg[T->e[i^1].v]-2;
ans=add(ans,1ll*d*(d-1)>>1);
}
printf("%d\n",ans);
break;
}
case 4:printf("%d\n",T->calc());break;
default:{
fp(i,1,k+1)solve(1,0,0,i);
printf("%d\n",ans);
break;
}
}
}
int main(){
// freopen("testdata.in","r",stdin);
T=&pool[0],E[0]=&pool[1],E[1]=&pool[2],ntr=&qwq;
n=read(),k=read(),T->Pre(n);
for(R int i=1,u,v;i<n;++i)u=read(),v=read(),++deg[u],++deg[v],T->Add(u,v),T->Add(v,u);
fp(i,2,N-1)lg[i]=lg[i>>1]+1;
fp(i,1,N-1)pc[i]=pc[i>>1]+(i&1);
fp(i,0,N-1)C[i][0]=1;fac[0]=1;
fp(i,1,14)fac[i]=mul(fac[i-1],i);
fp(i,1,14)fp(j,1,i)C[i][j]=add(C[i-1][j],C[i-1][j-1]);
fp(i,15,N-1)fp(j,1,14)C[i][j]=add(C[i-1][j],C[i-1][j-1]);
spj();
return 0;
}

洛谷P4337 [ZJOI2018]线图(状压+搜索+乱搞)的更多相关文章

  1. 【题解】洛谷P3959 [NOIP2017TG] 宝藏(状压DP+DFS)

    洛谷P3959:https://www.luogu.org/problemnew/show/P3959 前言 NOIP2017时还很弱(现在也很弱 看出来是DP 但是并不会状压DP 现在看来思路并不复 ...

  2. 洛谷P2761 软件补丁问题 [状压DP,SPFA]

    题目传送门 软件补丁问题 题目描述 T 公司发现其研制的一个软件中有 n 个错误,随即为该软件发放了一批共 m 个补丁程序.每一个补丁程序都有其特定的适用环境,某个补丁只有在软件中包含某些错误而同时又 ...

  3. 洛谷P2704 [NOI2001]炮兵阵地 [状压DP]

    题目传送门 炮兵阵地 题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图 ...

  4. 洛谷 P3622 [APIO2007]动物园【状压dp】

    看成网络流建图想了好久... 实际上5个是可以状压的 设f[i][k]为到第i个围栏状态为k的方案数,因为考虑到重复,设g[i][k]记录i开始,状态为k的孩子有几个 状态转移很好想:f[j][k]= ...

  5. 洛谷 P2473 [SCOI2008]奖励关(状压dp+期望)

    题面 luogu 题解 \(n \leq 15\) 状压 \(f[i][S]\)表示第\(i\)轮,吃过的集合为\(S\) 正着转移好像有点复杂 考虑逆推转移(正着转移应该也行) \(f[i][S]\ ...

  6. 洛谷 P1278 单词游戏 【状压dp】

    题目描述 Io和Ao在玩一个单词游戏. 他们轮流说出一个仅包含元音字母的单词,并且后一个单词的第一个字母必须与前一个单词的最后一个字母一致. 游戏可以从任何一个单词开始. 任何单词禁止说两遍,游戏中只 ...

  7. 洛谷P2761 软件补丁问题(状压DP,SPFA)

    题意 描述不清... Sol 网络流24题里面怎么会有状压dp?? 真是狗血,不过还是简单吧. 直接用$f[sta]$表示当前状态为$sta$时的最小花费 转移的时候枚举一下哪一个补丁可以搞这个状态 ...

  8. 洛谷P2831 愤怒的小鸟——贪心?状压DP

    题目:https://www.luogu.org/problemnew/show/P2831 一开始想 n^3 贪心来着: 先按 x 排个序,那么第一个不就一定要打了么? 在枚举后面某一个,和它形成一 ...

  9. 洛谷P2051 [AHOI2009] 中国象棋(状压dp)

    题目简介 n*m的棋盘,对每行放炮,要求每行每列炮数<=2,求方案数%9999973 N,M<=100 题目分析 算法考虑 考虑到N,M范围较小,每一行状态只与前面的行状态有关,考虑状压D ...

随机推荐

  1. Spark之 Spark Streaming流式处理

    SparkStreaming Spark Streaming类似于Apache Storm,用于流式数据的处理.Spark Streaming有高吞吐量和容错能力强等特点.Spark Streamin ...

  2. linux: cat more less tail head查看文件内容

  3. java求最长公共子串的长度

    1这道题目就是给定两个字符串,然后求这两个字符串的最长公共子串的最大长度,假设我的f()方法是来求两个字符串的最大公共子串,从头开始逐一比较,如果相等,则 继续调用这个方法,使得递归的长度+1,如果不 ...

  4. NSArray 快速求和、平均值、最大值、最小值

    在iOS开发中我们经常遇到一个需求,求一个数组的所有元素的和,最大值,最小值或者平均值,有的开发者可能第一想到的是for循环遍历求解,其实苹果提供了更简便的方式.如下: NSArray *arr = ...

  5. oracle的约束隐式创建索引和先索引后约束的区别

    oracle的约束隐式创建索引和先索引后约束的区别 两种情况:1.对于创建约束时隐式创建的索引,在做删除操作的时候: 9i~11g都会连带删除该索引 2.对于先创建索引,再创建约束(使用到此索引)这种 ...

  6. ubuntu下搭建android开发环境

    注意: google可能被和谐了,那就修改hosts sudo vim /etc/hosts 增加: #Google主页 203.208.46.146 www.google.com #这行是为了方便打 ...

  7. myeclipse10.X以上的破解方法

    破解补丁下载地址:http://pan.baidu.com/s/1dDzVP3z 本文使用的破解补丁对MyEclipse Standard/ Professional/ Blue/ Spring的10 ...

  8. p4980 polya定理

    传送门 分析 orz ymh 代码 #include<iostream> #include<cstdio> #include<cstring> #include&l ...

  9. Sed命令n,N,d,D,p,P,h,H,g,G,x解析3

    摘自:https://blog.csdn.net/WMSOK/article/details/78463199 Sed命令n,N,d,D,p,P,h,H,g,G,x解析 2017年11月06日 23: ...

  10. 有一个5ml 的瓶子 和3ml 的瓶子 和 很多水 现在 要取出4ml的水 请写出编程 多种解法

    //TODO public class demo { public static void main(String[] args) { demo.ss(); demo.sss(); } public ...