数学相关内容总结

筛法

有待填坑

莫比乌斯反演

基本定义

若定义

F(n)=\sum_{d|n}f(d)

,则有f(n)=\sum_{d|n}\mu(d)F(\frac{n}{d})

其中,\mu(d)称为莫比乌斯函数,其值为

\mu(d)=1,d=1\mu(d)=(-1)^r,d=\Pi_{i=1}^rp_i

其余情况下\mu(d)=0

基本性质

性质1

\sum_{d|n}\mu(d)=0,d\geq1

证明:

考虑d中的质数个数,仅需计算其函数值不为0的情况即可

则有\sum_{d|n}\mu(d)=\sum_{i=2_p}^nC_n^i-\sum_{i=2p-1}^nC_n^i=(1-1)^n=0

性质2

莫比乌斯函数为积性函数

证明:|\frac{n}{d}}f(d)=\sum_{d|n}f(d)\sum_{d|\frac{n}{d`}}\mu(d)=f(n)$$

例题

有待填坑

杜教筛

可以用来求积性函数在10^{10}左右的前缀和。

首先定义Dirichlet卷积:

(f * g)(n)=\sum_{d|n}f(d) * g(\frac{n}{d})

l(n)=(f * g)(n),再定义F(x),G(x),L(x)为以上三个函数的前缀和,则有

L(n)-g(1)F(n)=\sum_{i=2}^{n}g(i)F(\lfloor \frac{n}{i}\rfloor)

例题

[51NOD]莫比乌斯函数之和

#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<cmath>
#define N 7000000
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;

LL x,y,n,size;
bool flag[N+10];
int mu[N+10],p[700000];
int sum[N+10];
LL a[500010],b[500010];

inline int Abs(int x){return (x<0)?-x:x;}
inline int Min(int a,int b){return (a<b)?a:b;}
inline int Max(int a,int b){return (a>b)?a:b;}

inline int read(){
    int p=0;    char    c=getchar();
    while (c<48||c>57)  c=getchar();
    while (c>=48&&c<=57)    p=(p<<1)+(p<<3)+c-48,c=getchar();
    return p;
}

inline void Ready(){
    LL i=0,j=0,x=0;
    mu[1]=1;
    for (i=2;i<=N;i++){
        if (!flag[i])   {mu[i]=-1;  p[++p[0]]=i;}
        for (j=i*i;j<=N;j+=i)   flag[j]=1;
        for (j=1;j<=p[0];j++){
            if (i*p[j]>N)   break;
            if (i%p[j]) mu[i*p[j]]=-mu[i];
            else {
                mu[i*p[j]]=0;   break;
            }
        }
    }
    for (i=1;i<=N;i++)  sum[i]=sum[i-1]+mu[i];
}

inline LL &ID(LL x){
    return (x<=size)?a[x]:b[n/x];
}

inline LL Cal(LL x){
    LL i=0,cnt=1,l=0;
    if (x<=N)   return sum[x];
    LL &y=ID(x);
    if (y!=a[0])    return y;
    for (i=2;i<=x;i=l+1){
        l=x/(x/i);
        cnt-=(l+1-i)*Cal(x/i);
    }
    return y=cnt;
}

inline LL Work(LL x){
    if (x<=N)   return sum[x];
    size=(int)sqrt(x);  n=x;
    memset(a,-23333,sizeof(a)); memset(b,-23333,sizeof(b));
    return Cal(x);
}

int main(){
    scanf("%lld%lld",&x,&y);
    Ready();
    cout<<Work(y)-Work(x-1)<<endl;
    return 0;
}

未完待续

FFT&NTT

原理

对于形如y_n=\sum x_ih_{n-i}的式子,称为y对xh的卷积。

定义多项式A(x)=\sum_{i=0}^{n-1} a_{i}x^i

这种表示法称为系数表示法。由拉格朗日插值法可知,一个n次多项式可以通过n+1个点唯一确定。这种表示法称为点值表示法。

FFT进行多项式乘法运算的原理为,首先将系数表示法转化为点值表示法,然后在线性时间内计算出新的多项式的点值表示法,再转化回系数表示法。其核心部分在于如何快速实现两种表示法的转换。

首先定义主n次单位根:\omega_n=e^{\frac{2\pi i}{n}}

对于单位根,有如下三个引理:

1.消去引理

\omega_{dn}^{dk}=\omega_n^k

证明:写成指数形式即可证明

2.折半引理

当n为偶数时,n个n次单位根平方的集合等于n/2个n/2次单位根平方的集合

证明:

(\omega_n^{k})^2=\omega_{\frac{n}{2}}^k

(\omega_n^{k+\frac{n}{2}})^2=\omega_n^{2k+n}=\omega_n^n\omega_{\frac{n}{2}}^k=\omega_{\frac{n}{2}}^k

3.求和引理

对于不能被n整除的整数k,有

\sum_{j=0}^{n-1}(\omega_n^k)^j=0

证明:

由几何级数的求和公式易证。

由秦九韶公式可知,对于一个n次多项式求单点的值,时间复杂度为线性的。为了将系数表示法转化为点值表示法,需要n+1个点的值。总的时间内复杂度变为了平方级。FFT的核心思想便是利用n次单位根的性质,将这一过程优化到O(nlogn)

说点什么
支持Markdown语法
好耶,沙发还空着ヾ(≧▽≦*)o
Loading...