首页 > 其他分享 >P5900 无标号无根树计数 题解

P5900 无标号无根树计数 题解

时间:2024-04-24 15:13:40浏览次数:22  
标签:P5900 limits int 题解 sum 6000050 exp dfrac 无根树

不懂为啥都要对原式神秘转化之后再牛顿迭代,直接对原式牛顿迭代即可!完全不用转化!

设无标号有根树的组合类是 \(\mathcal T\),则有 \(\mathcal T=\mathcal Z\times\mathrm{MSET}(\mathcal T)\),即 \(T(x)=x\exp\sum\limits_{j\ge1}\dfrac{T(x^j)}j\),

设 \(G(F(x))=F(x)-x\exp\sum\limits_{j\ge1}\dfrac{F(x^j)}j=0\),要求 \(F(x)\bmod x^n\),问题变为牛顿迭代的形式。

首先钦定 \(F(x)\bmod x^1=[x^0]F(x)=0\)(否则 \(\exp\sum\limits_{j\ge1}\dfrac{F(x^j)}j\) 的常数项不收敛),

然后假设已经求出模 \(x^{\frac n2}\) 意义下的解 \(F_0(x)\),则模 \(x^n\) 意义下的解 \(F(x)\equiv F_0(x)-\dfrac{G(F_0(x))}{G'(F_0(x))}\pmod{x^n}\),

考虑如何求 \(G'(F_0(x))\)。

观察到 \(G(F_0(x))=F_0(x)-x\exp F_0(x)\exp\sum\limits_{j\ge2}\dfrac{F_0(x^j)}j\),

设最终答案是 \(H(x)\)(这里 \(H(x)\) 是与 \(F_0(x)\) 无关的常量),

则 \(\forall j\ge2\),有 \(F_0(x^j)\equiv H(x^j)\pmod{x^n}\),则 \(\exp\sum\limits_{j\ge2}\dfrac{F_0(x^j)}j\equiv\exp\sum\limits_{j\ge2}\dfrac{H(x^j)}j\pmod{x^n}\),

于是 \(\exp\sum\limits_{j\ge2}\dfrac{F_0(x^j)}j\) 是与 \(F_0(x)\) 无关的常量,

则 \(G'(F_0(x))=1-x\exp F_0(x)\exp\sum\limits_{j\ge2}\dfrac{F_0(x^j)}j=1-x\exp\sum\limits_{j\ge1}\dfrac{F_0(x^j)}j\),

于是 \(F(x)\equiv F_0(x)-\dfrac{G(F_0(x))}{G'(F_0(x))}\equiv F_0(x)-\dfrac{F_0(x)-x\exp\sum\limits_{j\ge1}\dfrac{F_0(x^j)}j}{1-x\exp\sum\limits_{j\ge1}\dfrac{F_0(x^j)}j}\pmod{x^n}\)。

没有封装多项式类,所以代码比较混乱邪恶,建议谨慎阅读。

#include <cstdio>
#include <cstring>
#include <algorithm>
#define int long long
#define G 3
#define _G 332748118
#define M 998244353
using namespace std;
int n, l, r[6000050], f[6000050], g[6000050], h[6000050], x[6000050], y[6000050], z[6000050], k[6000050], v[6000050];
int P(int x, int y)
{
    int q = 1;
    for (; y; y >>= 1, x = x * x % M)
        if (y & 1)
            q = q * x % M;
    return q;
}
void F(int *f, int n, int v)
{
    for (int i = 0; i < n; ++i)
        if (i < r[i])
            swap(f[i], f[r[i]]);
    for (int L = 2, m; L <= n; L <<= 1)
    {
        m = L >> 1;
        int W = P(v == 1 ? G : _G, (M - 1) / L);
        for (int l = 0, r = L - 1; r <= n; l += L, r += L)
        {
            int o = 1;
            for (int p = l; p < l + m; ++p)
            {
                int x = f[p], y = f[p + m];
                f[p] = (x + o * y) % M, f[p + m] = (x + M - o * y % M) % M;
                o = o * W % M;
            }
        }
    }
}
void I(int *f, int *g, int n)
{
    memset(g, 0, n << 4);
    memset(x, 0, n << 4);
    g[0] = P(f[0], M - 2);
    int L;
    for (L = 4;; L <<= 1)
    {
        memcpy(x, f, L << 2);
        memcpy(y, g, L << 3);
        l = __lg(L);
        for (int i = 0; i < L; ++i)
            r[i] = r[i >> 1] >> 1 | (i & 1) << l - 1;
        F(x, L, 1);
        F(y, L, 1);
        for (int i = 0; i < L; ++i)
            x[i] = x[i] * y[i] % M;
        F(x, L, -1);
        int _ = P(L, M - 2);
        for (int i = 0; i < L; ++i)
            x[i] = (M - x[i] * _ % M) % M;
        x[0] = (x[0] + 2) % M;
        memset(x + (L >> 1), 0, L << 2);
        F(g, L, 1);
        F(x, L, 1);
        for (int i = 0; i < L; ++i)
            g[i] = g[i] * x[i] % M;
        F(g, L, -1);
        for (int i = 0; i < L; ++i)
            g[i] = g[i] * _ % M;
        if (L >> 1 >= n)
            break;
    }
    memset(g + n, 0, L - n << 3);
}
void LN(int *f, int *g, int n)
{
    memset(h, 0, n << 4);
    for (int i = 0; i < n - 1; ++i)
        h[i] = (i + 1) * f[i + 1] % M;
    I(f, g, n);
    int L = 1;
    while (L >> 1 < n)
        L <<= 1;
    l = __lg(L);
    for (int i = 0; i < L; ++i)
        r[i] = r[i >> 1] >> 1 | (i & 1) << l - 1;
    F(g, L, 1);
    F(h, L, 1);
    for (int i = 0; i < L; ++i)
        h[i] = g[i] * h[i] % M;
    F(h, L, -1);
    int _ = P(L, M - 2);
    for (int i = 0; i < L; ++i)
        h[i] = h[i] * _ % M;
    g[0] = 0;
    for (int i = 1; i < n; ++i)
        g[i] = h[i - 1] * P(i, M - 2) % M;
    memset(g + n, 0, L - n << 3);
}
void EXP(int *f, int *g, int n)
{
    memset(g, 0, n << 4);
    g[0] = 1;
    int L;
    for (L = 4;; L <<= 1)
    {
        LN(g, z, L >> 1);
        for (int i = 0; i < L >> 1; ++i)
            z[i] = (f[i] + M - z[i]) % M;
        z[0] = (z[0] + 1) % M;
        l = __lg(L);
        for (int i = 0; i < L; ++i)
            r[i] = r[i >> 1] >> 1 | (i & 1) << l - 1;
        F(g, L, 1);
        F(z, L, 1);
        for (int i = 0; i < L; ++i)
            g[i] = g[i] * z[i] % M;
        F(g, L, -1);
        int _ = P(L, M - 2);
        for (int i = 0; i < L; ++i)
            g[i] = g[i] * _ % M;
        memset(g + (L >> 1), 0, L << 2);
        if (L >> 1 >= n)
            break;
    }
    memset(g + n, 0, L - n << 3);
}
signed main()
{
    v[1] = 1;
    for (int i = 2; i <= 6e6; ++i)
        v[i] = (M - M / i) * v[M % i] % M;
    scanf("%lld", &n), ++n;
    for (int L = 4;; L <<= 1)
    {
        memset(g, 0, L << 2);
        for (int i = 1; i < L >> 2; ++i)
            for (int j = i; j < L >> 1; j += i)
                g[j] = (g[j] + f[i] * i % M * v[j]) % M;
        EXP(g, k, L >> 1);
        for (int i = (L >> 1) - 1; i >= 1; --i)
            k[i] = (M - k[i - 1]) % M;
        k[0] = 1;
        I(k, g, L >> 1);
        k[0] = 0;
        for (int i = 1; i < L >> 2; ++i)
            k[i] = (k[i] + f[i]) % M;
        F(g, L, 1);
        F(k, L, 1);
        for (int i = 0; i < L; ++i)
            g[i] = g[i] * k[i] % M;
        F(g, L, -1);
        int _ = P(L, M - 2);
        for (int i = 0; i < L; ++i)
            g[i] = g[i] * _ % M;
        for (int i = 0; i < L >> 1; ++i)
            f[i] = (f[i] + M - g[i]) % M;
        if (L >> 1 >= n)
            break;
    }
    --n;
    int q = f[n];
    for (int i = (n >> 1) + 1; i < n; ++i)
        q = (q + M - f[i] * f[n - i] % M) % M;
    if (!(n & 1))
    {
        int u = f[n >> 1];
        q = (q + M - u * (u - 1) % M * (M + 1 >> 1) % M) % M;
    }
    printf("%lld", q);
    return 0;
}

标签:P5900,limits,int,题解,sum,6000050,exp,dfrac,无根树
From: https://www.cnblogs.com/5k-sync-closer/p/18155502

相关文章

  • abc340E题解
    题目描述样例input:5312345240output:04272算法1(树状数组)$O(nlogn)$本题我们可以看作对于每一个查询位置x我们都需要先把该位置上的所有球拿出来,然后再一个一个的放到对应位置上去。假设x位置上面有y个球,那么对于这y个球,如果大于n,那么就对所有的位置放y......
  • P3667 Bovine Genomics Hash+二分题解
    砂金听说了你在学字符串,于是在CLOI里出了道题给你P3667BovineGenomics题链:洛谷hzoi提高\(hash\)基础题。思路是二分答案,\(check\)中比较每一个区间字串的\(hash\)值是否相等。比较的时候可以用\(set\)或\(map\)。\(set\)的好处在于无重元素,判断时先将\(a\)串中区间子串......
  • 抢先看!美团、京东、360等大厂面试题解析,技术面试必备。
    技术面试必备!美团、京东、360等大厂面试题详解,让你轻松应对各大公司面试挑战!往期硬核面经哦耶!冲进腾讯了!牛逼!上岸腾讯互娱和腾讯TEG!腾讯的面试,强度拉满!前几篇文章分享了上岸腾讯的最新面经。不少粉丝股东留言说别只发腾讯的啦,其他大厂的也安排一些吧,比如美团、360、京东的......
  • [ABC329C] Count xxx 题解
    [ABC329C]Countxxx题解题目分析目的:统计本质不同而不是位置不同的所有字符都相同的字串。需要理解一下什么是本质不同而不是位置不同。结合样例1去理解这句话。列举样例1中的所有所有组成字符相同的字串。aaabaa编号字串位置\(1\)a\([1,1]\)\(2\)aa\([1......
  • [题解]ARC176 A~B
    赛时心态崩了,0pts遗憾离场……今天在学校冷静思考了下。发现B题思路其实很简单,不过A题怎么也没有想到,回来看了题解,其实思路也很简单,不过是自己思考方向错了。看来打比赛心态很重要,如果能冷静下来思考结果会好很多。果然算法竞赛不能被常理所束缚(笑)A-01MatrixAgain行列从\(0......
  • 题解 UOJ577【[ULR #1] 打击复读】
    题解UOJ577【[ULR#1]打击复读referencehttps://www.cnblogs.com/crashed/p/17382894.htmlhttps://www.cnblogs.com/sizeof127/articles/17579027.html字符串——黄建恒,广东实验中学题目描述为了提升搜索引擎的关键词匹配度以加大访问量,某些网站可能在网页中无意义复读大......
  • 编译用于Qt的opencv问题解决
    CMakewasunabletofindabuildprogramcorrespondingto"MinGWMakefiles"解释:这个错误表明CMake无法找到用于生成Makefiles的构建程序。在使用CMake生成项目文件时,如果指定了"MinGWMakefiles",CMake需要一个Make工具来构建项目,而这个工具通常是由MinGW提供的。如......
  • macOS配置Clion用于STM32开发找不到stdint.h等头文件问题解决方案
    问题编译工程时发现出现大量类似错误如下/opt/homebrew/Cellar/arm-none-eabi-gcc/13.2.0/lib/gcc/arm-none-eabi/13.2.0/include/stdint.h:9:16:fatalerror:stdint.h:Nosuchfileordirectory问题原因不能使用brewinstallarm-none-eabi-gcc安装编译工具链[1]解决方......
  • 「洛谷」题解:P1720 月落乌啼算钱(斐波那契数列)
    题目传送门比较经典的一道斐波那契数列的模版题,原题中给了一个很复杂的公式(也就是下面这个),但是实际上题目跟它毛关系没有……(所以放这个公式干什么)\[F_n=\dfrac{\left(\frac{1+\sqrt{5}}{2}\right)^n-\left(\frac{1-\sqrt{5}}{2}\right)^n}{\sqrt{5}}\]看见题解去了有很多人都......
  • AtCoder Beginner Contest 350 A - G 题解
    AtCoderBeginnerContest350A-PastABCsSolution把最后三个字符转成数字判断即可Code#include<bits/stdc++.h>usingnamespacestd;intmain(){strings;cin>>s;s=s.substr(3,3);intx=0;x=(s[0]-'0')*100+(s[1]-�......