单位根反演学习笔记

其实考试的时候,考到了这个知识点。发现自己不太会,就赶紧来学一下。

ps:好像学了之后也不会做那道考试题。

前置芝士

  • 单位根(FFT用到的那个东西)
  • 简单的数学推导基础。

单位根反演

其实也就是一个柿子:

\(\Large \displaystyle \ \ \ \ \ \ \ \ \ \qquad [n\mid a] = {1\over n}\sum_{i=0}^{n-1}w_n^{ai}\)

\([n|a]\) 表示 \(n\) 整除 \(a\) 的时候 \([n\mid a]\) 的值为 \(1\), 否则为 \(0\)\(w_n^{a_i}\) 则表示 \(n\) 次单位根。

证明的话,也很好证,分两种情况讨论一下就好了,具体如下:

  • \(a\nmid n\)\(a\mod n \neq 0\)的时候:

    后面的部分其实是个等比数列求和的形式,利用公式可得:

    \(\displaystyle \text{原式} = {1\over n}\sum_{i=0}^{n-1} w_n^{a_i}= {1\over n}\left(w_n^{0}\times {1-w_n^{an}\over 1-w_n^{a}}\right) = {1\over n} \left({w_{n}^{0}-w_n^{a_n}\over 1-w_n^a }\right)\)

    又因为:\(w_n^0 = 1, w_n^{a_n} = 1\), 所以 \(w_n^{0} - w_{n}^{an} = 0\)

    分子为 \(0\), 但分母不为 \(0\), 所以整个柿子的值为 \(0\)

  • \(a\mid n\)\(a\equiv 0\pmod n\) 的时候:

    \(\displaystyle \text{原式} = {1\over n}\sum_{i=0}^{n-1}w_n^{ai} = {1\over n}\sum_{i=0}^{n-1} w_{n}^{ai\pmod n} = {1\over n}\sum_{i=0}^{n-1} w_{n}^{0} = 1\)

有上面的柿子还可以推导出来另外一个柿子:

  • \([a\equiv b\pmod n] = [a-b\equiv 0\pmod n] = [n\mid (a-b)] = \displaystyle {1\over n}\sum_{i=0}w_{n}^{ai-bi} = {1\over n}\sum_{i=0}^{n-1}w_{n}^{ai}w_{n}^{-b_i}\)

一般这两个柿子就是单位根反演的常见形式。

例题/应用

1.LJJ 学二项式定理

\(\left[\displaystyle\sum_{i=0}^{n}{n\choose i}\times s^i\times a_{i\text{mod}4}\right]\pmod {998244353}\) 的结果。

有一个很显然的做法就是枚举 \(a_0,a_1,a_2,a_3\) 算他们的系数即:

\(\displaystyle\sum_{i=0}^{n}{n\choose i}\times s^i\times a_{i\text{mod}4}\)

\(\displaystyle =\sum_{i=0}^3a_i \sum_{j=0}^{n} [j\equiv i (\text{mod} \ 4)] \times {n\choose j}\times s^j\)

可以发现中间的那个 \([j\equiv i\text{mod 4}]\) 是单位根反演的柿子,带进去可得:

\(原式 = \displaystyle{1\over 4}\sum_{i=0}^3a_i\sum_{j=0}^{n}{n\choose j}\times s^j\sum_{k=0}^{3}w_{4}^{(j-i)k}\)

\(\displaystyle ={1\over 4}\sum_{i=0}^3a_i\sum_{j=0}^{n}{n\choose j}\times s^j\sum_{k=0}^3w_{4}^{jk}w_{4}^{-ik}\)

交换求和顺序,先枚举 \(k\) 可得:

\(原式 = \displaystyle {1\over 4}\sum_{i=0}^{3}a_i\sum_{k=0}^{3}w_{4}^{-ik}\sum_{j=0}^{n}{n\choose j}\times s^j\times w_{4}^{jk}\)

不难发现后面的枚举 \(j\) 的部分是个二项式定理的形式,化简一下可得:

\(\displaystyle 原式= {1\over 4}\sum_{i=0}^3a_i\sum_{k=0}^3w_{4}^{-ik} \times (sw_{4}^k+1)^{n}\)

由于 \(w_{n}^{i} = (g^{p-1\over n})^i\), 所以快速幂直接算即可。

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define int long long
const int p = 998244353;
int T,n,s,ans,g,inv4,a[5],w[5];
inline int read()
{
    int s = 0,w = 1; char ch = getchar();
    while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
    while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0'; ch = getchar();}
    return s * w;
}
int ksm(int a,int b)
{
    int res = 1;
    for(; b; b >>= 1)
    {
        if(b & 1) res = res * a % p;
        a = a * a % p;
    }
    return res;
}
signed main()
{
    T = read(); w[0] = 1; inv4 = ksm(4,p-2), g = ksm(3,(p-1)/4);
    for(int i = 1; i <= 3; i++) w[i] = w[i-1] * g % p;
    while(T--)
    {
        n = read(); s = read(); ans = 0;
        for(int i = 0; i <= 3; i++) a[i] = read();
        for(int i = 0; i <= 3; i++)
        {
            int sum = 0;
            for(int j = 0; j <= 3; j++)
            {
                sum = (sum + ksm(s*w[j]%p+1,n) * ksm(ksm(g,i*j),p-2) % p) % p;
            }
            ans = (ans + sum * a[i] % p) % p;
        }
        printf("%lld\n",ans*inv4%p);
    }
    return 0;
}

参考资料: 单位根反演小记

posted @ 2021-03-26 15:43  genshy  阅读(107)  评论(0编辑  收藏  举报