狄利克雷卷積

一、介紹

狄利克雷卷積是一種數論函數的一種特殊卷積形式,命名來自於德國數學家彼得·戴利克雷。對於兩個數論函數f(n)和g(n),它們的狄利克雷卷積定義為:

(f * g)(n) = Σd|n f(d)g(n/d)

其中,d是n的正因子。狄利克雷卷積有着廣泛的應用,例如在數論中,可以用來定義歐拉函數、除數函數等常見的數論函數;在組合數學中,可以用來計算多項式間的卷積,從而計算組合數的乘積。

二、性質

狄利克雷卷積具有以下的一些性質:

  1. 狄利克雷卷積是交換的,即f * g = g * f。
  2. 對於任意正整數n,(f * g)(n)=0當且僅當f(n’)=0或g(n’)=0,其中n’為n的任一因子。
  3. 單位函數1與任意函數f卷積的結果仍為f本身,即1 * f = f。
  4. 如果f(1)≠0,那麼f與其本身的卷積f * f在n>1的時候恆不為零。

三、應用

1. 求解歐拉函數

歐拉函數是一個關於正整數n的數論函數,表示小於或等於n的正整數中與n互質的數的數目,記為φ(n)。歐拉函數可以使用狄利克雷卷積來定義:

φ(n) = (1 * f)(n)

其中,f(n)表示一個分段函數,在n是合數的情況下,f(n)等於0,在n是質數的情況下,f(n)=n-1。

2. 求解除數函數

除數函數表示一個數的除數個數,記為d(n)。除數函數也可以使用狄利克雷卷積來定義,具體來說,我們需要兩個函數:

d(n)= (1 * f)(n)
g(n)=1

其中,f(n)表示一個分段函數,在n是合數的情況下,f(n)等於0,在n是質數的情況下,f(n)=2。

這樣,d(n) = (f * g)(n)。

3. 求解多項式卷積

多項式卷積是指給定兩個多項式f(x)和g(x),求解它們的乘積h(x)=f(x)g(x)的過程。這個過程可以使用狄利克雷卷積來實現。

具體來說,我們將f(x)和g(x)中的係數視作數論函數:對於f(x)來說,它的係數函數為f(k),表示f中次數為k的項的係數;對於g(x)來說,它的係數函數為g(k),表示g中次數為k的項的係數。這樣,h(x)的係數函數就為(f * g)(k)。

有了h(x)的係數函數,我們就可以把它轉化為多項式的形式,得到多項式卷積的結果。

四、代碼示例

1. 求解歐拉函數

#include <bits/stdc++.h>
using namespace std;

const int N = 1e6;

bool isprime[N+5];
int phi[N+5];
vector<int> primes;

void sieve() {
  memset(isprime, true, sizeof(isprime));
  isprime[1] = false;
  for (int i = 2; i  N) break;
      isprime[p*i] = false;
      if (i % p == 0) {
        phi[p*i] = phi[i] * p;
        break;
      } else {
        phi[p*i] = phi[i] * (p-1);
      }
    }
  }
}

int main() {
  sieve();
  for (int i = 1; i <= 20; i++) {
    cout << "phi(" << i << ") = " << phi[i] << endl;
  }
  return 0;
}

2. 求解除數函數

#include <bits/stdc++.h>
using namespace std;

const int N = 1e6;

bool isprime[N+5];
int d[N+5];
vector<int> primes;

void sieve() {
  memset(isprime, true, sizeof(isprime));
  isprime[1] = false;
  d[1] = 1;
  for (int i = 2; i  N) break;
        if (i % p == 0) {
          int cnt = 0;
          int x = i;
          while (x % p == 0) {
            cnt++;
            x /= p;
          }
          d[p*i] = d[x] * (cnt+1);
          break;
        } else {
          d[p*i] = d[i] * 2; 
        }
      }
    }
  }
}

int main() {
  sieve();
  for (int i = 1; i <= 20; i++) {
    cout << "d(" << i << ") = " << d[i] << endl;
  }
  return 0;
}

3. 求解多項式卷積

#include <bits/stdc++.h>
using namespace std;
using cd = complex<double>;

const double PI = acos(-1);
const int N = 2e5 + 5;

void fft(vector<cd> &a, bool invert) {
  int n = a.size();
  for (int i = 1, j = 0; i < n; i++) {
    int bit = n >> 1;
    while (j >= bit) {
      j -= bit;
      bit >>= 1;
    }
    j += bit;
    if (i < j) swap(a[i], a[j]);
  }

  for (int len = 2; len <= n; len <<= 1) {
    double ang = 2 * PI / len * (invert ? -1 : 1);
    cd wlen(cos(ang), sin(ang));
    for (int i = 0; i < n; i += len) {
      cd w(1);
      for (int j = 0; j < len/2; j++) {
        cd u = a[i+j], v = w * a[i+j+len/2];
        a[i+j] = u + v;
        a[i+j+len/2] = u - v;
        w *= wlen;
      }
    }
  }

  if (invert) {
    for (int i = 0; i < n; i++) {
      a[i] /= n;
    }
  }
}

vector<int> multiply(vector<int> &a, vector<int> &b) {
  vector<cd> fa(a.begin(), a.end()), fb(b.begin(), b.end());
  int n = 1;
  while (n < a.size() + b.size()) {
    n <<= 1;
  }
  fa.resize(n);
  fb.resize(n);

  fft(fa, false);
  fft(fb, false);
  for (int i = 0; i < n; i++) {
    fa[i] *= fb[i];
  }
  fft(fa, true);

  vector<int> ret(n);
  for (int i = 0; i < n; i++) {
    ret[i] = round(fa[i].real());
  }
  while (!ret.empty() && ret.back() == 0) {
    ret.pop_back();
  }
  return ret;
}

void multiply_inplace(vector<int> &a, vector<int> &b) {
  vector<cd> fa(a.begin(), a.end()), fb(b.begin(), b.end());
  int n = 1;
  while (n < a.size() + b.size()) {
    n <<= 1;
  }
  fa.resize(n);
  fb.resize(n);

  fft(fa, false);
  fft(fb, false);
  for (int i = 0; i < n; i++) {
    fa[i] *= fb[i];
  }
  fft(fa, true);

  a.resize(n);
  for (int i = 0; i < n; i++) {
    a[i] = round(fa[i].real());
  }
  while (!a.empty() && a.back() == 0) {
    a.pop_back();
  }
}

int main() {
  vector<int> a = {1, 2, 3}, b = {4, 5, 6};
  auto c = multiply(a, b);
  for (auto x : c) {
    cout << x << " ";
  }
  cout << endl;
  multiply_inplace(a, b);
  for (auto x : a) {
    cout << x << " ";
  }
  cout << endl;
  return 0;
}

原創文章,作者:OKEVH,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/332608.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
OKEVH的頭像OKEVH
上一篇 2025-01-24 18:46
下一篇 2025-01-24 18:47

相關推薦

  • 亞像素卷積詳解

    一、亞像素卷積的基本概念 亞像素卷積是一種計算機視覺領域的技術,是用於圖像縮放的重要方法。圖像縮放的目的是將一個圖像的大小調整為另一個尺寸,從而使其在不同環境下更適合使用。亞像素卷…

    編程 2025-04-23
  • ST-GCN:骨骼動作識別的圖卷積神經網絡

    一、ST-GCN簡介 ST-GCN(Spatial Temporal Graph Convolutional Network)是一種基於圖卷積神經網絡的動作分類算法,能夠對通過骨骼…

    編程 2025-04-23
  • PyTorch卷積神經網絡

    卷積神經網絡(CNN)是深度學習的一個重要分支,它在圖像識別、自然語言處理等領域中表現出了出色的效果。PyTorch是一個基於Python的深度學習框架,被廣泛應用於科學計算和機器…

    編程 2025-04-13
  • 卷積的定義及其應用

    一、什麼是卷積? 卷積是一種數學運算,它將兩個函數之間的關係通過一種特定的方式進行運算,求得它們之間的重疊部分。卷積是一種重要的方法,在信號處理、圖像處理、物理學、數學等領域都有廣…

    編程 2025-02-25
  • 卷積和池化:從原理到實踐

    一、卷積原理 卷積神經網絡中的核心操作就是卷積(Convolution),它可以提取出某些特徵信息。那麼,卷積是什麼,如何實現的? 卷積是一種線性運算,它可以將一個函數和另一個函數…

    編程 2025-02-05
  • DetNet: 深度可分離卷積網絡介紹

    一、DetNet簡介 DetNet是一種基於深度可分離卷積的網絡結構,用於目標檢測任務。它由南京大學和首都師範大學的研究團隊提出並於2018年發表在ECCV上。DetNet主要特點…

    編程 2025-02-05
  • 狄利克雷過程

    狄利克雷過程(Dirichlet Process, DP)是貝葉斯統計學中一個非常重要的概率過程,它是一種無限可分布的隨機過程。狄利克雷過程的引入,可以很好的處理聚類問題中,聚類中…

    編程 2025-02-01
  • 卷積核數量對神經網絡模型訓練的影響

    一、概述 卷積神經網絡是深度學習中常用的一種神經網絡結構,使用卷積核對輸入數據進行特徵提取和降維,從而實現對輸入數據的分類或回歸。而卷積核的數量則是影響神經網絡性能和訓練效果的重要…

    編程 2025-01-27
  • 卷積操作:從入門到實戰

    一、卷積操作概述 卷積操作是機器學習中常用的一種運算,用於卷積神經網絡中的數據處理。卷積操作可以有效地提取出數據集中的特徵,並對其進行分類、識別等任務。其本質是一種特殊的加權平均運…

    編程 2025-01-20
  • 卷積後的尺寸怎麼計算

    卷積是深度學習中非常重要的操作之一,可以輕鬆地對圖像、語音、文本等數據進行處理和分析。在進行卷積操作時,需要計算卷積核在特徵圖上移動的步長、填充值和卷積核的大小等參數。對於卷積後得…

    編程 2025-01-20

發表回復

登錄後才能評論