单位根反演

单位根反演

通常用于求 [xi]fi

形式#

[nk]=1ni=0n1ωnik

其中 ωnn 次单位根,模意义下可以被原根替换。

证明

nk 时,ωnki=1。所以右边等于 1ni=0n11=1

nk 时,右边等比数列求和:

1n×ωnnk1ωnk1

因为 ωnnk=1 所以柿子等于 0

推论#

一个更加常用的形式:设 F(x)=i=0nfixi,有

i=0n[pi]fi=1pj=0p1F(ωpj)

从原形式推一下就行。

不一定要从 x0 开始。有 x 的负次幂项也是可以的。

LibreOJ #6485#

给定 T105n,s,a0,a1,a2,a3,求

[i=0n((ni)siai mod 4)] mod 998244353

1n1018,1s,a0,a1,a2,a3108

i0,1,2,3(mod 4) 分类讨论:

i0(mod 4) 时:

即求 S0=a0i=0n[4i](ni)si

构造 F0(x)=(sx+1)n,单位根反演,S0=a04j=03F0(gj),其中 gmod 9982443534 次单位根。

i1(mod 4) 时:

即求 S1=a1i=0n[4(i1)](ni)si

构造 F1(x)=F0(x)x=i=0n(ni)sixi1,那么 S1=a14j=03F1(gj)

i2(mod 4)i3(mod 4) 的情况类似。

Code
#include <bits/stdc++.h>
const int mod = 998244353;
using ia = long long;

int T;
ia n, s, a[4];

inline ia qpow(ia b, ia p) {
    ia res = 1;
    for (; p; p >>= 1) {
        if (p & 1)
            res = res * b % mod;
        b = b * b % mod;
    }
    return res;
}

int main() {
    scanf("%d", &T);
    while (T--) {
        scanf("%lld%lld", &n, &s);
        for (int i = 0; i < 4; i++)
            scanf("%lld", &a[i]);
        ia G = qpow(3, (mod - 1) >> 2);

        ia S[4] = {0, 0, 0, 0};
        for (int j = 0; j < 4; j++) {
            ia x = qpow(G, j);
            ia inv_x = qpow(x, mod - 2);
            for (int i = 0; i < 4; i++)
                (S[i] += qpow((s * x + 1) % mod, n) * qpow(inv_x, i)) %= mod;
        }
        for (int j = 0; j < 4; j++)
            S[j] = S[j] * a[j] % mod * qpow(4, mod - 2) % mod;
        std::cout << (S[0] + S[1] + S[2] + S[3]) % mod << '\n';
    }
    return 0;
}

作者:zzxLLL

出处:https://www.cnblogs.com/zzxLLL/p/18016534

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   zzxLLL  阅读(40)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示