第六章 积性函数

第六章 积性函数(数学)

6.1 笔记

  • 积性函数

    • 定义:若函数 f : N → R f:N\rightarrow R f:NR,满足 ∀ p , q ∈ Z + ( p ≠ q ) \forall p,q\in Z^+(p\ne q) p,qZ+(p=q) ( p , q ) = 1 \color{red}(p,q)=1 (p,q)=1,都有 f ( p q ) = f ( p ) f ( q ) f(pq)=f(p)f(q) f(pq)=f(p)f(q),则称 f f f 为积性函数。

    • 实例

      1. 1 ( n ) = 1 1(n)=1 1(n)=1
      2. i d ( n ) = n id(n)=n id(n)=n
      3. ε ( n ) = [ n = 1 ] \varepsilon(n) = [n=1] ε(n)=[n=1]
      4. φ ( n ) = 1 , . . . , n \varphi(n)=1,...,n φ(n)=1,...,n 中与 n n n 中互质的数的数量
      5. d ( n ) = n d(n)=n d(n)=n 的正因子的数量
    • 性质:若 f ( x ) , g ( x ) f(x),g(x) f(x),g(x) 是积性函数,则 h ( x ) = f ( x ) g ( x ) h(x)=f(x)g(x) h(x)=f(x)g(x) 也是积性函数

    • 计算:设 n = p 1 α 1 p 2 α 2 . . . p k α k n=p_1^{\alpha_1}p_2^{\alpha_2}...p_k^{\alpha_k} n=p1α1p2α2...pkαk,则
      f ( n ) = f ( p 1 α 1 ) f ( p 2 α 2 ) . . . f ( p k α k ) f(n)=f(p_1^{\alpha_1})f(p_2^{\alpha_2})...f(p_k^{\alpha_k}) f(n)=f(p1α1)f(p2α2)...f(pkαk)
      利用质因数分解 f ( n ) f(n) f(n)

      ll get_f(ll n){
          ll ans = 1;
          rep(i, 2, n / i){
              int cnt = 0;
              while(n % i == 0) cnt++, n /= i;
              ans *= f(i, cnt);  //f(p, k) = f(p ^ k)
          }
          if(n  > 1) ans *+ f(n, 1);
          return ans;
      }
      

      利用欧拉筛计算 f ( 1 ) , . . . , f ( n ) f(1),...,f(n) f(1),...,f(n)

      int primes[N], is_prime[N], f[N], cnt = 0, mfcnt[N];
      ll calc_f(ll p, ll k){
          ...
      }
      void Eoula(int n){
          memset(is_prime, 1, sizeof(is_prime)); 
          is_prime[1] = 0, f[1] = 1;
          rep(mf, 2, n){
              if(is_prime[mf]) primes[++cnt] = mf, f[mf] = calc_f(mf, 1), mfcnt[mf] = 1;
              for(int j = 1; j <= cnt && mf * primes[j] <= n; j++){
                  is_prime[primes[j] * mf] = 0;
                  if(mf % primes[j] == 0){
                      mfcnt[primes[j] * mf] = mfcnt[mf] + 1;
                      f[primes[j] * mf] = f[mf] / calc_f(primes[j], mfcnt[mf]) * calc_f(primes[j], mfcnt[mf] + 1);
                      break;
                  }
                  else{
                      mfcnt[primes[j] * mf] = 1;
                      f[primes[j] * mf] = calc_f(primes[j], 1) * f[mf];
                  }
              }
          }
      }
      
  • 莫比乌斯(Mobius)反演

    引入:已知 f ( n ) = ∑ i = 1 n g ( i ) f(n)=\sum\limits_{i=1}^{n}g(i) f(n)=i=1ng(i),则可通过 f f f 计算出 g g g,即 g ( n ) = f ( n ) − f ( n − 1 ) g(n)=f(n)-f(n-1) g(n)=f(n)f(n1)

    • 已知 f ( n ) = ∑ d ∣ n g ( d ) f(n)=\sum\limits_{d\mid n}g(d) f(n)=dng(d),则要通过 f f f 计算出 g g g​。

      证明
      g ( n ) = g ( p 1 α 1 p 2 α 2 . . . p k α k ) = ∑ S ⊆ { 1 , 2 , . . . , k } ( − 1 ) ∣ S ∣ f ( p 1 α 1 − i 1 p 2 α 2 − i 2 . . . p k α k − i k ) 其 中    i j = { 1 , j ∈ S 0 , j ∉ S 令    μ ( n ) = μ ( p 1 i 1 p 2 i 2 . . . p k i k ) = { ( − 1 ) k , 若    i 1 = i 2 = . . . = i k = 1 0 , o t h e r s \begin{aligned} g(n)=&g(p_1^{\alpha_1}p_2^{\alpha_2}...p_k^{\alpha_k} )\\ =&\sum\limits_{S\subseteq \{1,2,...,k\}}(-1)^{|S|}f(p_1^{\alpha_1-i_1}p_2^{\alpha_2-i_2}...p_k^{\alpha_k-i_k})\qquad其中\;i_j=\begin{cases}1,j\in S\\0,j\notin S \end{cases}\\ 令\;\mu(n)=&\mu(p_1^{i_1}p_2^{i_2}...p_k^{i_k})=\begin{cases}(-1)^k,\quad 若\;i_1=i_2=...=i_k=1 \\0,\qquad others \end{cases} \end{aligned} g(n)==μ(n)=g(p1α1p2α2...pkαk)S{1,2,...,k}(1)Sf(p1α1i1p2α2i2...pkαkik)ij={1,jS0,j/Sμ(p1i1p2i2...pkik)={(1)k,i1=i2=...=ik=10,others

    • 莫比乌斯反演:设 f : N → R f:N\rightarrow R f:NR g : N → R g:N\rightarrow R g:NR 是两个函数,则
      f ( n ) = ∑ d ∣ n g ( d )    ⟺    g ( n ) = ∑ d ∣ n μ ( n d ) f ( d ) , 其 中 μ ( n ) = { ( − 1 ) k , n 无 平 方 因 子 且 有 k 个 质 因 子 0 , n 有 平 方 因 子 \color{red}f(n)=\sum\limits_{d\mid n}g(d)\iff g(n)=\sum\limits_{d\mid n}\mu(\dfrac{n}{d})f(d),\\ 其中 \mu(n)=\begin{cases}\begin{aligned}&(-1)^k,&&n无平方因子且有k个质因子\\&0,&&n有平方因子 \end{aligned}\end{cases} f(n)=dng(d)g(n)=dnμ(dn)f(d),μ(n)={(1)k,0,nkn
      其中, μ ( x ) \mu(x) μ(x) 为积性函数,可用欧拉筛求

      int primes[N], is_prime[N], mu[N], cnt = 0;
      void Euler(int n){
          memset(is_prime, 1, sizeof(is_prime)); 
          is_prime[1] = 0, mu[1] = 1;
          rep(mf, 2, n){
              if(is_prime[mf]){
                  primes[++cnt] = mf;
                  mu[mf] = -1;
              }
              for(int j = 1; j <= cnt && mf * primes[j] <= n; j++){
                  is_prime[primes[j] * mf] = 0;
                  if(mf % primes[j] == 0) break;
                  mu[primes[j] * mf] = -mu[mf];
              }
          }
      }
      
    • 环计数问题

    • 莫比乌斯反演2:设 f : N → R f:N\rightarrow R f:NR g : N → R g:N\rightarrow R g:NR 是两个函数,且存在正整数 n n n,对于所有 n > N n>N n>N,有 f ( n ) = g ( n ) = 0 f(n)=g(n)=0 f(n)=g(n)=0,则
      f ( n ) = ∑ n ∣ m , m ≤ N g ( m )    ⟺    g ( n ) = ∑ n ∣ m , m ≤ N μ ( m n ) f ( m ) \color{red}f(n)=\sum\limits_{n\mid m,m\le N}g(m)\iff g(n)=\sum\limits_{n\mid m, m\le N}\mu\left(\dfrac{m}{n} \right)f(m) f(n)=nm,mNg(m)g(n)=nm,mNμ(nm)f(m)

6.2 习题

地址:第六章习题

A. 模板题【线性筛求积性函数】

//积性函数筛
#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i--)
#define ll long long
#define db double
#define VI vector<int>
#define PII pair<int, int>
const db Pi = 3.141592653589793;
const int INF = 0x7fffffff;
const int N = 1e7 + 5;
const db eps = 1e-10;
int cas, n, m, a[N];
int primes[N], is_prime[N], f[N], cnt = 0, mfcnt[N];
ll calc_f(ll p, ll k){
    return k + 1;
}
void getprime(int n){
    memset(is_prime, 1, sizeof(is_prime)); 
    is_prime[1] = 0, f[1] = 1;
    rep(mf, 2, n){
        if(is_prime[mf]) primes[++cnt] = mf, f[mf] = calc_f(mf, 1), mfcnt[mf] = 1;
        for(int j = 1; j <= cnt && mf * primes[j] <= n; j++){
            is_prime[primes[j] * mf] = 0;
            if(mf % primes[j] == 0){
                mfcnt[primes[j] * mf] = mfcnt[mf] + 1;
                f[primes[j] * mf] = f[mf] / calc_f(primes[j], mfcnt[mf]) * calc_f(primes[j], mfcnt[mf] + 1);
                break;
            }
            else{
                mfcnt[primes[j] * mf] = 1;
                f[primes[j] * mf] = calc_f(primes[j], 1) * f[mf];
            }
        }
    }
}
int main(){
    getprime(10000000);
    cin >> cas;
    while(cas--){
        scanf("%d", &n);
        printf("%d\n", f[n]);
    }
}
/*
5
1
2
3
4
5
*/

B. 华华给月月出题

  • 题目链接:华华给月月出题

  • 题目:计算 ⨁ i = 1 n ( i n ( m o d 1 0 9 + 7 ) ) 1 ≤ n ≤ 1.3 × 1 0 7 \bigoplus\limits_{i=1}^{n}(i^n\pmod{10^9+7})\quad 1\le n\le 1.3\times 10^7 i=1n(in(mod109+7))1n1.3×107

  • 思路:由于 f ( i ) = i n f(i)=i^n f(i)=in 为积性函数,即 f ( p q ) = ( p q ) n = p n ⋅ q n = f ( p ) f ( q ) f(pq)=(pq)^n=p^n\cdot q^n=f(p)f(q) f(pq)=(pq)n=pnqn=f(p)f(q)

    • 快速幂计算 f ( p ) f(p) f(p):约有 n ln ⁡ n \dfrac{n}{\ln n} lnnn 个质数,每个快速幂复杂度为 O ( log ⁡ n ) O(\log n) O(logn)
    • 欧拉筛计算 f ( i ) = i n f(i)=i^n f(i)=in:复杂度为 O ( n ) O(n) O(n)

    总复杂度为 O ( n ln ⁡ n log ⁡ n + n ) ≈ O ( n ) O(\dfrac{n}{\ln n}\log n+n)\approx O(n) O(lnnnlogn+n)O(n)

#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i--)
#define ll long long
#define db double
#define VI vector<int>
#define PII pair<int, int>
const db Pi = 3.141592653589793;
const int INF = 0x7fffffff;
const int N = 1.3e7 + 5;
const db eps = 1e-10;
const ll mod = 1e9 + 7;
int n, ans;
int primes[N], is_prime[N], f[N], cnt = 0, mfcnt[N];
ll power(ll a, ll b, ll mod){
    ll ans = 1;
    if(mod == 1) ans = 0;
    while(b > 0){
        if(b % 2 == 1) (ans *= a) %= mod;
        (a *= a) %= mod;
        b >>= 1;
    }
    return ans;
}
void getprime(ll n){
    memset(is_prime, 1, sizeof(is_prime)); 
    is_prime[1] = 0, f[1] = 1;
    rep(mf, 2, n){
        if(is_prime[mf]){
            primes[++cnt] = mf;
            f[mf] = power(mf, n, mod);
        }
        for(int j = 1; j <= cnt && mf * primes[j] <= n; j++){
            is_prime[primes[j] * mf] = 0;
            f[primes[j] * mf] = (ll)f[primes[j]] * f[mf] % mod;
            if(mf % primes[j] == 0) break;
        }
    }
}
int main(){
    cin >> n;
    getprime(n);
    ans = f[1];
    rep(i, 2, n) ans = ans ^ f[i];
    cout << ans << endl;
}
/*
3
in2
2005117
out2
863466972
*/

C. 序列

  • 题目链接:序列

  • 题目:两个长度为 n n n 的序列,求满足 gcd ⁡ ( x , y ) = 1 \gcd(x,y)=1 gcd(x,y)=1 a b x = b a y a_{b_x}=b_{a_y} abx=bay 的对 ( x , y ) (x,y) (x,y) 的数量。 1 ≤ n ≤ 1 0 5 , 1 ≤ a i , b i ≤ n 1\le n\le 10^5, 1\le a_i,b_i\le n 1n105,1ai,bin

  • 知识点:反演

  • 思路:求 ∑ 1 ≤ x , y ≤ n [ a b x = b a y ] ⋅ [ gcd ⁡ ( x , y ) = 1 ] \sum\limits_{1\le x, y\le n}[a_{b_x}=b_{a_y}]\cdot [\gcd(x,y)=1] 1x,yn[abx=bay][gcd(x,y)=1]

    • g ( d ) = ∑ 1 ≤ x , y ≤ n [ a b x = b a y ] ⋅ [ gcd ⁡ ( x , y ) = d ] g(d)=\sum\limits_{1\le x, y\le n}[a_{b_x}=b_{a_y}]\cdot [\gcd(x,y)=d] g(d)=1x,yn[abx=bay][gcd(x,y)=d],则
      f ( d ) = ∑ d ∣ d ′ g ( d ′ ) = ∑ d ∣ x , d ∣ y [ a b x = b a y ]    ⟺    g ( d ) = ∑ d ∣ d ′ , d ′ ≤ n μ ( d ′ d ) f ( d ′ ) ∴ g ( 1 ) = ∑ d ′ = 1 n μ ( d ′ ) f ( d ′ ) \color{red} f(d)=\sum\limits_{d\mid d'}g(d')=\sum\limits_{d\mid x,d\mid y}[a_{b_x}=b_{a_y}]\iff g(d)=\sum\limits_{d\mid d',d'\le n}\mu(\dfrac{d'}{d})f(d')\\ \therefore g(1)=\sum\limits_{d'=1}^n \mu(d')f(d') f(d)=ddg(d)=dx,dy[abx=bay]g(d)=dd,dnμ(dd)f(d)g(1)=d=1nμ(d)f(d)
#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i--)
#define ll long long
#define db double
#define VI vector<int>
#define PII pair<int, int>
const db Pi = 3.141592653589793;
const int INF = 0x7fffffff;
const int N = 1e5 + 5;
const db eps = 1e-10;
int n, a[N], b[N], f[N];
int primes[N], is_prime[N], mu[N], cnt = 0;
ll ans;
void Euler(int n){
    memset(is_prime, 1, sizeof(is_prime)); 
    is_prime[1] = 0, mu[1] = 1;
    rep(mf, 2, n){
        if(is_prime[mf]) primes[++cnt] = mf, mu[mf] = -1;
        for(int j = 1; j <= cnt && mf * primes[j] <= n; j++){
            is_prime[primes[j] * mf] = 0;
            if(mf % primes[j] == 0) break;
            mu[primes[j] * mf] = -mu[mf];
        }
    }
}
int main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin >> n;
    Euler(n);
    rep(i, 1, n) cin >> a[i];
    rep(i, 1, n) cin >> b[i];
    rep(d, 1, n){
        memset(f, 0, sizeof(f));
        for(int x = d; x <= n; x += d) f[a[b[x]]]++;
        for(int y = d; y <= n; y += d) ans += f[b[a[y]]] * mu[d];
    }
    cout << ans << endl;
}
/*
3
1 1 1
1 1 1
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值