首页 > 其他分享 >P7728 旧神归来 题解

P7728 旧神归来 题解

时间:2023-03-13 15:26:36浏览次数:49  
标签:P7728 int 题解 多项式 edge 消掉 旧神 include

日常生活:写多项式——写多项式题解——颓——写多项式——写多项式题解——颓——……

最近真的降智。大水题切不动。

#查询 gtm1514 精神状态

题解

好像挺清新的。

首先我们知道这是个多项式题。然后题目这个 b 东西不太好刻画,整点好搞的。

发现设 \(f_i\) 为当前有多少个深度为 \(i\) 的叶子比较好。

于是设出生成函数 \(F\)。假如当前最浅的叶子深度为 \(d\),那么一次变换可以写成:

\[F_i=(1+x^d)F_{i-1}-x^d \]

那考虑怎么表示一下连续的几次操作。设一次消掉 \(d\) 深度的一个叶子,后一次消掉 \(e\) 深度的一个叶子,那么

\[\begin{aligned} &(1+x^e)\left((1+x^d)F-x^d\right)-x^e\\ =&(1+x^e)(1+x^d)F-x^d-x^e-x^{d+e}\\ =&(1+x^e)(1+x^d)(F-1)+1 \end{aligned} \]

初始的 \(F_0\) 可以搜一遍得到。显然任意深度有限的叶子都可以被消掉。那么设深度为 \(i\) 的叶子需要 \(a_i\) 步消掉,有

\[(F-1)\prod_{i=1}(1+x^i)^{a_i}+1=0 \]

\[\prod_{i=1}(1+x^i)^{a_i}=\frac 1{1-F} \]

这东西如何处理我们是熟知的。取个 \(\ln\) 得到:

\[\sum_{i=1}a_i\ln(1+x^i)=-\ln(1-F) \]

\[\sum_{i=1}a_i\sum_{j=1}\frac{(-1)^{j-1}x^{ij}}j=-\ln(1-F) \]

右边一只 \(\log\) 爆算。左边一只 \(\log\) 爆算(当然我比较懒左边根号处理的)。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
const int mod=998244353;
int n,m,wl;
struct gra{
    int v,w,next;
}edge[200010];
int t,head[100010],ans[100010],f[300010],w[300010],g[300010],inv[300010];
void Add(int u,int v){
    edge[++t].v=v;edge[t].next=head[u];head[u]=t;
}
void dfs(int x,int fa,int d){
    bool jud=false;
    for(int i=head[x];i;i=edge[i].next){
        if(edge[i].v!=fa)dfs(edge[i].v,x,d+1),jud=true;
    }
    if(!jud)g[d]++;
}
#define add(x,y) (x+y>=mod?x+y-mod:x+y)
#define sub(x,y) (x<y?x-y+mod:x-y)
void get(int n){
	wl=1;
	while(wl<n)wl<<=1;
}
int qpow(int a,int b){
    int ans=1;
    while(b){
        if(b&1)ans=1ll*ans*a%mod;
        a=1ll*a*a%mod;
        b>>=1;
    }
    return ans;
}
void init(int n){
    int t=1;
    while((1<<t)<n)t++;
    t=min(t-1,21);
    w[0]=1;w[1<<t]=qpow(31,1<<21-t);inv[1]=1;
    for(int i=t;i;i--)w[1<<i-1]=1ll*w[1<<i]*w[1<<i]%mod;
    for(int i=1;i<(1<<t);i++)w[i]=1ll*w[i&(i-1)]*w[i&-i]%mod;
	for(int i=2;i<=n;i++)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
}
void DIF(int a[],int n){
    for(int mid=n>>1;mid>=1;mid>>=1){
        for(int i=0,k=0;i<n;i+=mid<<1,k++){
            for(int j=0;j<mid;j++){
                int x=1ll*a[i+j+mid]*w[k]%mod;
                a[i+j+mid]=sub(a[i+j],x);
                a[i+j]=add(a[i+j],x);
            }
        }
    }
}
void DIT(int a[],int n){
    for(int mid=1;mid<n;mid<<=1){
        for(int i=0,k=0;i<n;i+=mid<<1,k++){
            for(int j=0;j<mid;j++){
                int x=a[i+j+mid];
                a[i+j+mid]=1ll*sub(a[i+j],x)*w[k]%mod;
                a[i+j]=add(a[i+j],x);
            }
        }
    }
    int inv=qpow(n,mod-2);
    for(int i=0;i<n;i++)a[i]=1ll*a[i]*inv%mod;
    reverse(a+1,a+n);
}
#define mul(f,g,n) for(int i=0;i<n;i++)f[i]=1ll*f[i]*g[i]%mod
void getinv(int n,int f[],int g[]){
    get(n);
    static int tmp[300010],ret[300010];
    for(int i=0;i<wl;i++)g[i]=0;
    g[0]=qpow(f[0],mod-2);
    for(int len=2;len<=wl;len<<=1){
        memcpy(tmp,f,4*len);memcpy(ret,g,2*len);
        DIF(tmp,len);DIF(ret,len);mul(tmp,ret,len);
        DIT(tmp,len);
        memset(tmp,0,2*len);tmp[0]=mod-1;
        DIF(tmp,len);mul(ret,tmp,len);
        DIT(ret,len);
        for(int i=len>>1;i<len;i++)g[i]=sub(0,ret[i]);
    }
	for(int i=n;i<wl;i++)g[i]=0;
	for(int i=0;i<wl;i++)tmp[i]=ret[i]=0;
}
void dao(int f[],int n){
	for(int i=1;i<n;i++)f[i-1]=1ll*f[i]*i%mod;
	f[n-1]=0;
}
void jifen(int f[],int n){
	for(int i=n;i>=1;i--)f[i]=1ll*f[i-1]*inv[i]%mod;
	f[0]=0;
}
void getln(int n,int f[],int g[]){
    getinv(n,f,g);get(n<<1);
	for(int i=n;i<wl;i++)f[i]=g[i]=0;
    dao(f,wl);
    DIF(f,wl);DIF(g,wl);mul(g,f,wl);
    DIT(g,wl);
    jifen(g,wl);
	for(int i=n;i<wl;i++)g[i]=0;
}
int main(){
    scanf("%d%d",&n,&m);init(m+1<<1);
    for(int i=1;i<n;i++){
        int u,v;scanf("%d%d",&u,&v);
        Add(u,v);Add(v,u);
    }
    dfs(1,0,0);
    for(int i=0;i<=n;i++)g[i]=sub(0,g[i]);
    g[0]=add(g[0],1);
    getln(m+1,g,f);
    for(int i=1;i<=m;i++)f[i]=sub(0,f[i]);
    for(int k=1;k<=m;k++){
        ans[k]=f[k];
        for(int i=1;i*i<=k&&i<k;i++){
            if(k%i==0){
                int ret=1ll*inv[k/i]*ans[i]%mod;
                if((k/i)&1)ans[k]=sub(ans[k],ret);
                else ans[k]=add(ans[k],ret);
                if(i*i!=k&&i!=1){
                    ret=1ll*inv[i]*ans[k/i]%mod;
                    if(i&1)ans[k]=sub(ans[k],ret);
                    else ans[k]=add(ans[k],ret);
                }
            }
        }
    }
    for(int i=1;i<=m;i++){
        ans[i]=add(ans[i],ans[i-1]);
        printf("%d\n",ans[i]);
    }
    return 0;
}

标签:P7728,int,题解,多项式,edge,消掉,旧神,include
From: https://www.cnblogs.com/gtm1514/p/17211532.html

相关文章

  • [转]mysql问题解决SELECT list is not in GROUP BY clause and contains nonaggregate
    原文地址:mysql问题解决SELECTlistisnotinGROUPBYclauseandcontainsnonaggregatedcolumn-慕尘-博客园(cnblogs.com)今天在Ubuntu下的部署项目,发现一些好......
  • 【Pytorch】RuntimeError: cuDNN error: CUDNN_STATUS_NOT_INITIALIZED 问题解决
    问题起因:在运行论文代码时出现了RuntimeError:cuDNNerror:CUDNN_STATUS_NOT_INITIALIZED报错。 解决方法:如果不是cuda、cudnn配置的问题,那有可能是电脑的线......
  • 【磁盘空间不足问题解决】Docker 日志清理、
    问题描述:1、系统无法访问,提示“无法访问此网站”2、启动Docker镜像提示错误信息,如下:“Errorresponsefromdaemon:Cannotrestartcontainer7f812bfba45f:write/v......
  • 群晖提示无法安装此文件问题解决
    安装群晖的时候你可能会碰到如下情况:群晖安装DSM的时候提示:“无法安装此文件,文件可能已经毁损。(13)”还是讨厌的红色其实是U盘引导没有修改VID所致,用ChipGenius芯片精灵......
  • ARC158C All Pair Digit Sums 题解
    题目链接题意设\(f(x)\)表示\(x\)的各位之和。例如\(f(158)=1+5+8=14,f(2023)=2+0+2+3=7,f(1)=1\)等。给定一个正整数序列\(A=(A_1,...,A_N)\),求\(\sum_{i=1}^N......
  • 题解 ARC111B【Reversible Cards】
    我们将值域中每个数视作一个节点,将每张卡片视作连接两个节点的边,则问题转化为:对于每条边都选择一个端点,使得被选择的节点总数最大。显然每个连通块可以分开处理。设连通块......
  • 【题解】CF364D
    题目大意给定集合a,求最大的是大小超过一半的子集的最大公约数的数是什么。题解“超过一半”即想到随机化n次后只有\(\frac{1}{2^n}\)的几率错误,于是随机一个数判断它的......
  • 题解 P3306 [SDOI2013] 随机数生成器
    Link它\(p\)都是质数了,这不就明示我们是bsgs了吗我没看出来然后我们来倒一下\(n\)天的式子第一天是\(x_1\),第二天是\(ax_1+b\),第三天是\(a^2x_1+(ab+b)\),第四......
  • 【题解】CF1264D2
    题目大意给定一个长度为\(n\)的字符串,其中只有(,),?三种字符,其中?可以为(或者)对于一个括号序列,定义其权值为其通过删除字符后可以得到的合法的括号匹配的最深的深度,下......
  • AcWing 199. 余数之和 题解
    做了一下午……题解都看不懂,最后自己比比划划弄懂了。题意:给出\(n,k\),求\(\sum\limits_{i=1}^nk\modi\)。首先取模形式十分不好处理,所以我们可以根据取模运算定义做......