ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[学习笔记] 单位根反演

2022-07-20 16:35:08  阅读:122  来源: 互联网

标签:frac int sum 单位根 笔记 反演 define omega Mod


引入

单位根反演一般用于求一类 \(i \bmod k\) 的求和式,通过枚举 \(j \equiv i \pmod{k}\),将式子转化为 \(k\) 次单位根下的操作。这一般要求 \(k \mid (\mathrm{mod}-1)\)。通常会结合二项式定理使用。

单位根反演

在 FFT 中我们其实已经见过它了:

\[[n\mid k] = \frac{1}{n} \sum_{i=0}^{n-1} \omega_n^{ki} \]

让我们来证明一下:

  • 当 \(k \neq 0 \pmod{n}\) 时,由等比数列求和,右式等于 \(\frac{1}{n} \dfrac{\omega_n^{kn} - 1}{\omega_n^k-1}\),其中 \(\omega_n^k \neq 1\),而 \(\omega_n^{kn} = 1\),因此右式等于 \(0\)。

  • 当 \(k \equiv 0 \pmod{n}\) 时,此时 \(\omega_n^{ki} = 1\),等式显然成立。

容易得到如下推论:若 \(p \equiv q \pmod{n}\),即 \(p - q \equiv 0 \pmod{n}\),那么有:

\[[n \mid p-q] = \frac{1}{n} \sum_{i=0}^{n-1} \omega_n^{pi} \omega_n^{-qi} \]

求多项式特定倍数的系数和

\[\sum_{i=0}^{\lfloor \frac{n}{k} \rfloor} [x^{ik}] f(x) = \frac{1}{k} \sum_{j=0}^{k-1} f(\omega_k^j) \]

把多项式大力展开后运用单位根反演容易证明上式。改变求和顺序,上式也可以写成较为简洁的形式:

\[\sum_{k|n} [x^n] f(x) = \frac{1}{k} \sum_{i=0}^{k-1} f(\omega_k^i) \]

事实上上式与 CRT 和 Lagrange 插值公式具有奇妙的联系,但这和本文主题没有太大关系,因此在这里不做深入展开。不过因为它是实在是很美妙,大概还是会专门开一篇博客讲讲这个东西。

LOJ 6485 LJJ 学二项式定理

\[\sum_{i=0}^n C_{n}^i s^i a_{i \bmod 4} = \sum_{i=0}^n C_n^i s^i \sum_{j=0}^3 a_j [i \equiv j \ (\mathrm{mod} \ 4)] \]

根据推论,上式可化简为:

\[\begin{aligned} \frac{1}{4} \sum_{i=0}^n C_n^i s^i \sum_{j=0}^3 \sum_{k=0}^3 \omega_4^{ik} \omega_4^{-jk} &= \frac{1}{4} \sum_{j=0}^3 a_j \sum_{k=0}^3 \omega_4^{-jk} \sum_{i=0}^n C_n^i s^i \omega_4^{ik} \\ &= \frac{1}{4} \sum_{j=0}^3 a_j \sum_{k=0}^3 \omega_4^{-jk} (s \omega_4^k +1) ^n \end{aligned} \]

众所周知 \(998244353\) 的原根是 \(3\),因此 \(\omega_4^1 = 3\)。预处理单位根及其逆元即可做到 \(O(T \log n)\)。

Code
/*
最黯淡的一个 梦最为炽热
万千孤单焰火 让这虚构灵魂鲜活
至少在这一刻 热爱不问为何
存在为将心声响彻
*/
#include <bits/stdc++.h>
#define pii pair<int, int>
#define mp(x, y) make_pair(x, y)
#define pb push_back
#define eb emplace_back
#define fi first
#define se second
#define int long long
#define mem(x, v, n) memset(x, v, sizeof(int) * (n))
#define mcpy(x, y, n) memcpy(x, y, sizeof(int) * (n))
#define lob lower_bound
#define upb upper_bound
using namespace std;

inline int read() {
	int x = 0, w = 1;char ch = getchar();
	while (ch > '9' || ch < '0') { if (ch == '-')w = -1;ch = getchar(); }
	while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
	return x * w;
}

inline int min(int x, int y) { return x < y ? x : y; }
inline int max(int x, int y) { return x > y ? x : y; }

const int MN = 2e5 + 5;
const int Mod = 998244353;

inline void Pls(int &x, int y) { x += y; if (x >= Mod) x -= Mod; }
inline void Dec(int &x, int y) { x -= y; if (x < 0) x += Mod; }

inline int qPow(int a, int b = Mod - 2, int ret = 1) {
    while (b) {
        if (b & 1) ret = ret * a % Mod;
        a = a * a % Mod, b >>= 1;
    }
    return ret;
}

// #define dbg

int N, s, w[5], iw[5];

inline void Work() {
    N = read(), s = read();
    int ans = 0;
    for (int i = 0; i < 4; i++) {
        int x = read();
        int cur = 1, sig = 0;
        for (int j = 0; j < 4; j++) {
            sig = (sig + cur * qPow(s * w[j] % Mod + 1, N) % Mod) % Mod;
            cur = cur * iw[i] % Mod;
        }
        ans = (ans + x * sig % Mod) % Mod;
    }
    ans = ans * qPow(4) % Mod;
    printf("%lld\n", ans);
}

signed main(void) {
    w[0] = 1;
    w[1] = qPow(3, (Mod - 1) / 4);
    w[2] = w[1] * w[1] % Mod;
    w[3] = w[1] * w[2] % Mod;
    for (int i = 0; i <= 3; i++) iw[i] = qPow(w[i]);

    int T = read();
    while (T--) Work();
    return 0;
}

标签:frac,int,sum,单位根,笔记,反演,define,omega,Mod
来源: https://www.cnblogs.com/came11ia/p/16498145.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有