数论卷积相关

积性函数

如果函数是积性函数,那么只需要知道其在 1,pk 处的取值,那么已经完全了解了这个函数。这极大简化了问题。

随便看个例子:求因子和函数 σ 是什么。

首先证明是积性函数。考虑 id1=σ,因此是积性函数。

其次考虑其在 1,pk 处取值:image

因此可以乘起来就知道了。

接下来再看看欧拉函数是什么。怎么证明积性函数:

image

那是什么就乱证。

逆元,单位元的定义

单位元 e,也叫做幺元。其在一个半群 (D,)(前一个是元素集合,后一个是运算符)中被定义的话,半群被称作幺半群。

某一个元素 x 的逆元 x1,意思是 xx1=e

例如,
对于 =+e=0,因此 x+x1=0
对于 =×e=1,因此 x×x1=1
对于 =×(矩阵乘法),e= 单位矩阵(主对角线是 1 其他都是 0)。

Dirichlet 卷积

也叫乘法卷积。
对于两个数列 {an},{bn},定义 {cn}a,b 做狄利克雷卷积的结果。也称 c=ab。那么 i,ci=k|iakbik。朴素地进行一次狄利克雷卷积,时间复杂度为 O(nlnn)
性质:
对于两个积性函数 f,gfg 是积性函数。容易证明。(有什么用?积性函数有一些牛逼的筛法和性质)

在此基础上,定义一些特殊函数。

1 函数:1x=1,是完全积性函数。

e 函数:半群 (f,) 的单位元。考虑其性质:
ef=f
x=1 时,e1f1=1,显然 e1=1
x1 时,e1fx+e?f?...=1,显然 e?=0
因此 e={1,0,0,...,0}

μ 函数:也叫做莫比乌斯函数。是 1 函数的逆元。也即,1μ=e
x=1 时,11μ1=1,显然 μ1=1
x=p 时,11μp+1pμ1=0,显然 μp=1
为了简便,我们发现可以省去 1?。接着看看。
x=pk 时,μ1+μp+μp2+μp3+...,那么当 k>1 的时候 μpk=0
x=pq 时,μ1+μp+μq+μpq,那么 μpq=1
二项式反演得,μp1p2p3...pk=(1)k
x=p1a1p2a2...pkak 时,需要 μ=0
验证一下,确实能对的上。
因此 μx={(1)kxk0x

有一个东西是要注意到的。d|nfd 等于 f1

莫比乌斯反演

f1=g,gμ=f,第二个过程就是莫比乌斯反演。

有什么作用?对于某一项的性质可以追踪。例如 1xμx=ex,可以判断 [x=1]

莫比乌斯函数是积性函数,可以通过线性筛求。其中素数赋 1,最小质因子乘上的时候赋 0,否则赋相反数。

POI2007 Zap(BZOJ1101)

image

整除分块即可。这是非常经典的应用。虽然在 a=b 的时候具有 2φi1 的简便方法,但是这个推法显然是更为能够推广的。

拓展式子

φ1=id,其中 idx=x
证明:
首先这三个都是积性函数,因此只需证明对任意 pk 都成立,那么对所有正整数均成立。
考虑 φpk=pk1(p1)
因此 φpk1=i=1kpi1(p1)+1

image

得证。

狄利克雷前缀和

更优秀的求 a1 的方式。用 p 进赋值序列的视角看待,是一个高维前缀和。注意 1 没啥特别的,没有 1 这一维度。
时间复杂度 O(nloglogn),比一般的 O(nlogn) 要好。

P5495
f(i, 1, cnt) for(int j = p[i]; j <= n; j += p[i]) a[j] += a[j / p[i]];

类似地,可以卷 μ,也就是前缀和的逆运算。还不用筛。

f(i, 1, cnt) for(int j = n / p[i]; j >= 1; j --) a[j * p[i]] -= a[j];
P2714

gcd 卷积。 gcd(i,j)=1aibj

这个算超集和,就是 FMT。不需要显式的 p 进赋值序列,只需要直接枚举 p 即可。

注意卷积里面 a,b 分别是多少。

最后容斥做的时候一定要推清楚。系数是一个组合数行求和形式。

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define f(i, a, b) for(int i = (a); i <= (b); i++)
#define cl(i, n) i.clear(),i.resize(n);
#define endl '\n'
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int inf = 1e9;
//#define cerr if(false)cerr
#define freopen if(false)freopen
#define watch(x) cerr  << (#x) << ' '<<'i'<<'s'<<' ' << x << endl
void cmax(int &x, int y) {if(x < y) x = y;}
void cmin(int &x, int y) {if(x > y) x = y;}
//调不出来给我对拍!
const int v = 10000; 
int p[10010]; bool c[10010]; int cnt; int a[10010], b[5][10010];
void euler() {
    f(i, 2, v) {
        if(!c[i]) {p[++cnt] = i;}
        for(int j = 1; j <= cnt && p[j] * i <= v; j ++) {
            c[p[j] * i] = 1;
            if(i % p[j] == 0) break;
        }
    }
}

signed main() {
    ios::sync_with_stdio(0);
    cin.tie(NULL);
    cout.tie(NULL);
    //freopen();
    //freopen();
    //time_t start = clock();
    //think twice,code once.
    //think once,debug forever.
    euler(); 
    int n; 
    while(cin >> n) {
        memset(a, 0, sizeof(a)); memset(b, 0, sizeof(b)); 
        f(i, 1, n) {cin >> a[i]; b[1][a[i]] ++;}
        //对 b 做 gcd 卷积
        f(i, 1, v) b[0][i] = b[1][i];
        f(j, 1, cnt) { //维度
            for(int k = v / p[j]; k >= 1; k --) {
                b[0][k] = b[0][k * p[j]] + b[0][k]; 
            }
        }
        f(i, 1, 3) {
            //FWT
            f(j, 1, v) b[i + 1][j] = b[i][j];
            f(j, 1, cnt) { //维度
                for(int k = v / p[j]; k >= 1; k --) {
                    b[i + 1][k] = b[i + 1][k * p[j]] + b[i + 1][k]; 
                }
            }
            //点值乘法
            f(k, 1, v) b[i + 1][k] *= b[0][k];
            //IFWT
            f(j, 1, cnt) {
                for(int k = 1; k <= v / p[j]; k ++) b[i + 1][k] = b[i + 1][k] - b[i + 1][k * p[j]];
            }
        }
        b[2][1] -= b[1][1]; b[2][1] /= 2;
        b[3][1] -= b[1][1]; b[3][1] -= 6 * b[2][1]; b[3][1] /= 6;
        b[4][1] -= b[1][1]; b[4][1] -= 14 * b[2][1]; b[4][1] -= 36 * b[3][1]; b[4][1] /= 24;
        cout << b[4][1] << endl;
    }
    //time_t finish = clock();
    //cout << "time used:" << (finish-start) * 1.0 / CLOCKS_PER_SEC <<"s"<< endl;
    return 0;
}
/*
2023/x/xx
start thinking at h:mm


start coding at h:mm
finish debugging at h:mm
*/

狄利克雷除法

image

递推,先解出 G,时间复杂度 O(nlogn),然后卷。
总时间 O(nlogn)

性质

狄利克雷卷积有交换律和结合律。(这个乱证)

两个积性函数做狄利克雷除法的结果是积性函数。

powerful number 筛

powerful number,是没有非平方因子的数。n 的 powerful number 的规模是 O(n) 的。

image

时间复杂度 O(n×t)t 是查询一次 g 前缀和的时间。

2.2 模拟赛 T2 数论导数

【题意】
image
【分析】
image
怎么求 qddpowerful number 的时候的取值?首先 q 是积性函数。因此只需要知道 q1qpk 的取值就可以乘出所有取值。注意 k>1k=0 对所有 p 都成立。

image

积性函数的性质非常神奇,一定要懂得用。

posted @   OIer某罗  阅读(197)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏
· Manus爆火,是硬核还是营销?
点击右上角即可分享
微信分享提示