模板 - 数论函数

前64个自然数的表:

nmu(n)Smu(n)phi(n)Sphi(n)d(n)Sd(n)sigma(n)Ssigma(n)
111111111
2-10122334
3-1-1242548
40-12638715
5-1-2410210621
61-12124141233
7-1-2618216841
80-24224201556
90-26283231369
101-14324271887
11-1-210422291299
120-244663528127
13-1-3125823714141
141-266444124165
151-187244524189
160-188055031220
17-1-2169625218238
180-2610265839277
19-1-31812026020297
200-3812866642339
211-21214047032371
221-11015047436407
23-1-22217227624431
240-2818088460491
250-22020038731522
261-11221249142564
270-11823049540604
280-112242610156660
29-1-228270210330690
30-1-38278811172762
31-1-430308211332794
320-416324611963857
331-320344412348905
341-216360412754959
351-1243844131481007
360-1123969140911098
37-1-2364322142381136
381-1184504146601196
3910244744150561252
4000164908158901342
41-1-1405302160421384
42-1-2125428168961480
43-1-3425842170441524
440-3206046176841608
450-3246286182781686
461-2226504186721758
47-1-3466962188481806
480-316712101981241930
490-3427543201571987
500-3207746207932080
511-2328064211722152
520-2248306217982250
53-1-3528822219542304
540-31890082271202424
551-2409404231722496
560-22496482391202616
571-13610004243802696
58102810284247902786
59-1-15810862249602846
600-1161102122611683014
61-1-26011622263623076
621-13011924267963172
630-136122862731043276
640-132126072801273403

欧拉函数

不大于n的与n互质的数的个数。
对于n>2,欧拉函数都是偶数
单个欧拉函数:

inline int phi(int n) {
    int res=n;
    for(int i=1; i<=pritop&&pri[i]*pri[i]<=n; i++) {
        if(n%pri[i]==0) {
            res-=res/pri[i];
            while(n%pri[i]==0)
                n/=pri[i];
        }
        if(n==1)
            return res;
    }
    if(n!=1)
        res-=res/n;
    return res;
}

线性筛与杜教筛:

const int mod=1e9+7;
const int MAXN=5e6;

ll sphi[MAXN+1];
int pri[MAXN+1];
int &pritop=pri[0];

void sieve(int n=MAXN) {
    sphi[1]=1;
    for(int i=2; i<=n; i++) {
        if(!pri[i]) {
            pri[++pritop]=i;
            sphi[i]=i-1;
        }
        for(int j=1; j<=pritop; j++) {
            int &p=pri[j];
            int t=i*p;
            if(t>n)
                break;
            pri[t]=1;
            if(i%p) {
                sphi[t]=sphi[i]*sphi[p];
                if(sphi[t]>=mod)
                    sphi[t]%=mod;
            } else {
                sphi[t]=sphi[i]*p;
                if(sphi[t]>=mod)
                    sphi[t]%=mod;
                break;
            }
        }
    }
    for(int i=2; i<=n; i++) {
        sphi[i]+=sphi[i-1];
        if(sphi[i]>=mod)
            sphi[i]%=mod;
    }
}

unordered_map<ll,ll> Sphi;

inline ll Phi(ll n) {
    if(n<=MAXN)
        return sphi[n];
    if(Sphi.count(n))
        return Sphi[n];
    ll ret=s1(n);
    for(ll l=2,r; l<=n; l=r+1) {
        ll t=n/l;
        r=n/t;
        ll tmp=r-(l-1);
        tmp*=Phi(t);
        if(tmp>=mod)
            tmp%=mod;
        ret-=tmp;
        if(ret<0)
            ret+=mod;
    }
    return Sphi[n]=ret;
}

莫比乌斯函数

单个莫比乌斯函数:

inline int mu(int n){
    int res=1;
    for(int i=1; i<=pritop&&pri[i]*pri[i]<=n; i++) {
        if(n%pri[i]==0) {
            res=-res;
            n/=pri[i];
            if(n%pri[i]==0)
                return 0;
        }
        if(n==1)
            return res;
    }
    if(n!=1)
        res=-res;
    return res;
}

线性筛与杜教筛:

const int MAXN=5e6;

ll smu[MAXN+1];
int pri[MAXN+1];
int &pritop=pri[0];

void sieve(int n=MAXN) {
    smu[1]=1;
    for(int i=2; i<=n; i++) {
        if(!pri[i]) {
            pri[++pritop]=i;
            smu[i]=-1;
        }
        for(int j=1; j<=pritop; j++) {
            int &p=pri[j];
            int t=i*p;
            if(t>n)
                break;
            pri[t]=1;
            if(i%p) {
                smu[t]=-smu[i];
            } else {
                smu[t]=0;
                break;
            }
        }
    }
    for(int i=2; i<=n; i++) {
        smu[i]+=smu[i-1];
    }
}

unordered_map<ll,ll> Smu;
inline ll Mu(ll n) {
    if(n<=MAXN)
        return smu[n];
    if(Smu.count(n))
        return Smu[n];
    ll ret=1;
    for(ll l=2,r; l<=n; l=r+1) {
        ll t=n/l;
        r=n/t;
        ll tmp=r-(l-1);
        tmp*=Mu(t);
        ret-=tmp;
    }
    return Smu[n]=ret;
}

因数个数函数\(d(n)\)

线性筛:

前缀和:
一次分块就可以求出来,比杜教筛还快,要什么杜教筛?

ll d(int n){
    ll ret=0;
    for(int l=1,r;l<=n;l=r+1){
        r=n/(n/l);
        ret+=(r-l+1)*(n/l);
    }
    return ret;
}

除数函数\(\sigma _{x}(n)\)

积性。
n的所有因子的x次方和。
\(\sigma _{0}(n)\) 0阶的除数函数就是 \(d(n)\)


其他遇到过的奇怪组合

\(id(n)*d(n)\)

积性,但是有比杜教筛更快的办法:
只讨论前缀和,类似\(d(n)\),每次贡献的式子带个公差罢了。

int sum(int a1,int an,int n){
    return (a1+an)*n/2;
}

ll id_d(int n){
    ll ret=0;
    for(int l=1,r;l<=n;l=r+1){
        r=n/(n/l);
        ret+=sum(1,n/l,n/l)*sum(l,r,r-l+1);
    }
    return ret;
}

\(id(n)*\varphi(n)\)

显然积性,可以用杜教筛。
卷一个 \(id\) 用杜教筛,一般有几个 \(id\) 就卷几个 \(id\)

\(f(n)=id(n)*\varphi(n)\)
\(S(n)=\sum\limits_{i=1}^{n} f(i)\)

要求的就是\(S(n)\)

假如我们找到一个\(g\),使得\((f*g)(n)\)\(f\)\(g\)的狄利克雷卷积)的前缀和很好求,且\(g(n)\)也很好求,那么可以用杜教筛。

显然:
\((f*g)(n)=\sum\limits_{d|n} f(d)g(\frac{n}{d})=\sum\limits_{d|n} d\varphi(d)g(\frac{n}{d})\)

若令\(g(n)=n\),即\(g=id\),有:
\((f*g)(n)=n\sum\limits_{d|n} \varphi(d)\)

后面那个:
\(\sum\limits_{d|n} \varphi(d)=n\)

所以:
\((f*g)(n)=n^2\)

由杜教筛公式:
\(g(1)S(n)=\sum\limits_{i=1}^{n}(f*g)(i) - \sum \limits _{i=2}^{n} g(i) S(\lfloor \frac{n}{i} \rfloor)\)

由于某些特殊的原因,好像\(g(1)\)总是\(1\),代进去可以得到:
\(S(n)=\sum\limits_{i=1}^{n}i^2 - \sum \limits _{i=2}^{n} i S(\lfloor \frac{n}{i} \rfloor)\)

后面那个套一个分块就可以了。


可能会常用的公式:
\(s_1(n)=\sum\limits_{i=1}^{n}i=\frac{1}{2}n(n+1)\)
\(s_2(n)=\sum\limits_{i=1}^{n}i^2=\frac{1}{6}n(n+1)(2n+1)\)
\(s_3(n)=\sum\limits_{i=1}^{n}i^3=\frac{1}{4}n^2(n+1)^2\)

转载于:https://www.cnblogs.com/Yinku/p/10965052.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值