Ural 1560 牛顿恒等式 + 线段树

该博客介绍了如何运用牛顿恒等式解决关于基本对称多项式的计算问题。通过维护线段树,实现了在O(kqlogn)的时间复杂度内求解指定次数项的和,并递推出所有基本对称多项式。文章包含详细的算法实现及代码示例。
摘要由CSDN通过智能技术生成
题意

传送门 Ural 1560 Elementary Symmetric Functions

题解

根据牛顿恒等式
∑ i = 1 k S i b k − i + k × b k = 0 , k ∈ N + \sum\limits_{i=1}^{k} S_ib_{k-i} + k\times b_k = 0, k\in N^+ i=1kSibki+k×bk=0,kN+ 其中 S k = ∑ l ≤ i ≤ r a i k S_k = \sum_{l\leq i\leq r} a_i^k Sk=liraik,且 b k = ( − 1 ) k f k b_k = (-1)^kf_k bk=(1)kfk
f k = ∑ l ≤ i 1 < ⋯ < i k ≤ r ( ∏ m = 1 k x i m ) f_k = \sum\limits_{l\leq i_1<\dots <i_k\leq r}\Big(\prod\limits_{m=1}^{k}x_{i_m}\Big) fk=li1<<ikr(m=1kxim) 基本对称多项式 f f f 的边界情况 f 0 = 1 , f k = 0 ( k > r − l + 1 ) f_0 = 1, f_k = 0(k > r - l + 1) f0=1,fk=0(k>rl+1)

已知 k k k 次项求和结果,则可以递推出 f f f。维护 k k k 棵线段树即可。总时间复杂度 O ( k q log ⁡ n ) O(kq\log n) O(kqlogn)

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
constexpr int MAXN = 8E4 + 5, SZ = 1 << 18;
int N, M, P;
ll A[MAXN];

struct ST
{
    int lim;
    ll dat[SZ];
    void set(int x) { lim = x; }
    void init(int k = 0, int l = 0, int r = N)
    {
        if (r - l == 1)
        {
            ll t = 1;
            for (int i = 0; i < lim; ++i)
                t = t * A[l] % P;
            dat[k] = t;
            return;
        }
        int m = (l + r) / 2, chl = k * 2 + 1, chr = k * 2 + 2;
        init(chl, l, m), init(chr, m, r);
        dat[k] = (dat[chl] + dat[chr]) % P;
    }
    void change(int a, int b, ll x, int k = 0, int l = 0, int r = N)
    {
        if (r <= a || b <= l)
            return;
        if (a <= l && r <= b)
        {
            ll t = 1;
            for (int i = 0; i < lim; ++i)
                t = t * x % P;
            dat[k] = t;
            return;
        }
        int m = (l + r) / 2, chl = k * 2 + 1, chr = k * 2 + 2;
        change(a, b, x, chl, l, m), change(a, b, x, chr, m, r);
        dat[k] = (dat[chl] + dat[chr]) % P;
    }
    ll ask(int a, int b, int k = 0, int l = 0, int r = N)
    {
        if (a <= l && r <= b)
            return dat[k];
        int m = (l + r) / 2, chl = k * 2 + 1, chr = k * 2 + 2;
        if (b <= m)
            return ask(a, b, chl, l, m);
        else if (m <= a)
            return ask(a, b, chr, m, r);
        return (ask(a, b, chl, l, m) + ask(a, b, chr, m, r)) % P;
    }
} tr[4];

ll inv(ll x)
{
    ll res = 1, n = P - 2, mod = P;
    while (n > 0)
    {
        if (n & 1)
            res = res * x % mod;
        x = x * x % mod, n >>= 1;
    }
    return res;
}

int main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> N >> M >> P;
    for (int i = 0; i < N; ++i)
        cin >> A[i];
    for (int i = 0; i < 4; ++i)
    {
        tr[i].set(i + 1);
        tr[i].init();
    }
    while (M--)
    {
        char op;
        cin >> op;
        if (op == 'I')
        {
            int p, d;
            cin >> p >> d;
            --p;
            A[p] = (A[p] + d) % P;
            for (int i = 0; i < 4; ++i)
                tr[i].change(p, p + 1, A[p]);
        }
        else
        {
            int l, r, lim;
            cin >> l >> r >> lim;
            --l;
            vector<ll> s(lim + 1), f(lim + 1);
            for (int i = 0; i < lim; ++i)
                s[i + 1] = tr[i].ask(l, r);
            f[0] = 1;
            ll mod = P;
            for (int k = 1; k <= lim; ++k)
            {
                ll sum = 0;
                for (int i = 1; i <= k; ++i)
                {
                    ll d = s[i] * f[k - i] % mod;
                    if ((k - i) & 1)
                        d = mod - d;
                    sum += d;
                }
                if ((k + 1) & 1)
                    sum = mod - sum;
                sum = sum % mod * inv(k) % mod;
                f[k] = (sum + mod) % mod;
            }
            for (int i = 0; i <= lim; ++i)
                cout << f[i] << (i == lim ? '\n' : ' ');
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值