[xsy2289]B
题意:给一棵树,一次操作定义为删掉一条树边再加一条边,并且满足加完边后这还是一棵树,问在进行不超过$k$次操作后能构造出多少种不同的树
首先...矩阵树定理在边有边权的时候同样适用,这时可以把它看成重边,此时直接按原方法求得的是所有生成树的边权乘积之和
所以我们可以把这棵树补成一个完全图,令补上去的边边权为$x$,那么答案就是求出来的多项式的$0\cdots k$次系数之和
直接带着多项式做当然不行,所以我们就用单位根作为$x$,求值后IDFT回去即可
我的代码在$k=n-1$时会错...?
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long ll;
const int mod=998244353;
int mul(int a,int b){return a*(ll)b%mod;}
int ad(int a,int b){return(a+b)%mod;}
int de(int a,int b){return(a-b)%mod;}
int pow(int a,int b){
int s=1;
while(b){
if(b&1)s=mul(s,a);
a=mul(a,a);
b>>=1;
}
return s;
}
int rev[64],N,iN;
void pre(int n){
int i,k;
for(N=1,k=0;N<=n;N<<=1)k++;
for(i=0;i<N;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(k-1));
iN=pow(N,mod-2);
}
void ntt(int*a,int on){
int i,j,k,t,w,wn;
for(i=0;i<N;i++){
if(i<rev[i])swap(a[i],a[rev[i]]);
}
for(i=2;i<=N;i<<=1){
wn=pow(3,on==1?(mod-1)/i:mod-1-(mod-1)/i);
for(j=0;j<N;j+=i){
w=1;
for(k=0;k<i>>1;k++){
t=mul(w,a[i/2+j+k]);
a[i/2+j+k]=de(a[j+k],t);
a[j+k]=ad(a[j+k],t);
w=mul(w,wn);
}
}
}
if(on==-1){
for(i=0;i<N;i++)a[i]=mul(a[i],iN);
}
}
int d[64],tr[64][64],g[64][64],n;
int gauss(int n){
int i,j,k,t,c,s;
s=1;
for(i=1;i<=n;i++){
t=pow(g[i][i],mod-2);
for(j=i+1;j<=n;j++){
c=mul(t,g[j][i]);
for(k=i;k<=n;k++)g[j][k]=de(g[j][k],mul(c,g[i][k]));
}
s=mul(s,g[i][i]);
}
return s;
}
int solve(int x){
int i,j;
memset(g,0,sizeof(g));
for(i=1;i<=n;i++)g[i][i]=ad(d[i],mul(n-1-d[i],x));
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
if(i!=j){
if(tr[i][j])
(g[i][j]-=1)%=mod;
else
(g[i][j]-=x)%=mod;
}
}
}
return gauss(n-1);
}
int po[64];
int main(){
int k,i,x,s;
scanf("%d%d",&n,&k);
if(k==n-1){
printf("%d",pow(n,n-2));
return 0;
}
for(i=2;i<=n;i++){
scanf("%d",&x);
x++;
tr[x][i]=tr[i][x]=1;
d[x]++;
d[i]++;
}
pre(n);
for(i=0;i<N;i++)po[i]=solve(pow(3,(mod-1)/N*i));
ntt(po,-1);
s=0;
for(i=0;i<=k;i++)s=ad(s,po[i]);
printf("%d",ad(s,mod));
}
[xsy2289]B的更多相关文章
随机推荐
- HDU 2639 Bone Collector II (dp)
题目链接 Problem Description The title of this problem is familiar,isn't it?yeah,if you had took part in ...
- It is possible that this issue is resolved by uninstalling an existi
使用真机连接Android Studio测试时出现这样的错误: 解决方法: 设置Android Studio 中Instant Run中的选项为不选中 根据以下路径,找到Instant Run中的选项 ...
- Java 关于微信公众号支付总结附代码
很多朋友第一次做微信支付的时候都有蒙,但当你完整的做一次就会发现其实并没有那么难 业务流程和应用场景官网有详细的说明:https://pay.weixin.qq.com/wiki/doc/api/js ...
- 【Windows使用笔记】Windows日常使用软件
整理一些对于我来说日常使用的Windows软件. 排名不分先后,仅凭我想起来的顺序! 1 MadAppLauncher 这个对我来说非常需要了. 使用它可以快速启动日常常用的软件,非常快捷高效.一般来 ...
- 【Matlab】绘制饼状统计图
a=tabulate(b); % b为需要绘制饼图的原始数据列,生成新的一个矩阵a label={'1','2','3'} % 设定饼图每块扇形代表的内容 percent=num2str(a(:,3) ...
- LINUX-内核-中断分析-中断向量表(3)-arm【转】
转自:http://blog.csdn.net/haolianglh/article/details/51986987 arm中断概念 在<ARM体系结构与编程>第9章中说到,ARM 中有 ...
- Linux内核空间内存申请函数kmalloc、kzalloc、vmalloc的区别【转】
转自:http://www.th7.cn/system/lin/201606/167750.shtml 我们都知道在用户空间动态申请内存用的函数是 malloc(),这个函数在各种操作系统上的使用是一 ...
- python基础===self的理解
self是类的实例 self有点类似java中的this,无实际意义.但是约定俗成的都是用self表示类的实例 class A: def func(self): print(self) #指向的是类的 ...
- 经典卷积网络模型 — LeNet模型笔记
LeNet-5包含于输入层在内的8层深度卷积神经网络.其中卷积层可以使得原信号特征增强,并且降低噪音.而池化层利用图像相关性原理,对图像进行子采样,可以减少参数个数,减少模型的过拟合程度,同时也可以保 ...
- vue 文件引入
直接 <script> 引入 直接下载并用 <script> 标签引入,Vue 会被注册为一个全局变量.重要提示:在开发时请用开发版本,遇到常见错误它会给出友好的警告. 开发环 ...