线性筛求积性函数

先开始第一个问题:求正整数\(n(1\le n\le 10^7)\)的所有正因数的个数,\(q(1\le q\le10^5 )\)次询问 例题

我们规定\(n\)的正因子数目为\(d(n)\)\(n\)的最小质因子出现次数为\(e(n)\)
\(n={p_1}^{k_1}{p_2}^{k_2}...{p_c}^{k_c}({p_1}\lt{p_2}\lt...\lt{p_c})\)
\(d(n)=\prod_{i=1}^c(k_i+1)\)
\(e(n)=k_1\)
显然\(d(n)\)是一个积性函数: 对于\(gcd(a,b)=1\)\(d(a\times b)=d(a)\times d(b)\)恒成立

线性筛\(d(n)\):

#include <bits/stdc++.h>
using namespace std;
const int N=1e7+10;
typedef long long ll;
ll d[N],e[N],prime[N],c;
void solve(){
    d[1]=1;
    for(int i=2;i<N;i++){
        if(d[i]==0){
            prime[c++]=i;
            d[i]=2;
            e[i]=1;
        }
        for(int j=0;1LL*prime[j]*i<N;j++){
            if(i%prime[j]==0){
                d[i*prime[j]]=d[i]/(e[i]+1)*(e[i]+2);
                e[i*prime[j]]=e[i]+1;
                break;
            }
            d[i*prime[j]]=d[i]*d[prime[j]];
            e[i*prime[j]]=1;
        }
    }
}
int main(){
    ll q,n;
    scanf("%lld",&q);
    solve();
    while(q--){
        scanf("%lld",&n);
        printf("%lld\n",d[n]);
    }
    return 0;
}

华华给月月出题
\(Ans=\oplus_{i=1}^N(i^N mod(10^9+7))\) (\(\oplus\)表示异或和) \((1\le N\le 1.3\times 10^7)\)
对于\(f(i)=i^N\),显然有\(f(i\times j)=f(i)\times f(j)\)恒成立,那么我们称这种函数为完全积性函数
那么我们对每个素数直接用快速幂求出\(f\),线性筛求出其余的\(f\),最后再求异或和即可

Code

#include <bits/stdc++.h>
using namespace std;
const int N=2e7+10,mod=1e9+7;
typedef long long ll;
ll power(ll a,ll b){
    ll ans=1;
    for(;b;b>>=1){
        if(b&1) ans=ans*a%mod;
        a=a*a%mod;
    }
    return ans;
}
ll prime[N],fac[N],n,cnt;
bool vis[N];
void solve(){
    fac[1]=1;
    for(int i=2;i<=n;i++){
        if(!vis[i]) {
            prime[++cnt]=i;
            fac[i]=power(i,n);
        }
        for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
            vis[i*prime[j]]=1;
            fac[i*prime[j]]=fac[i]*fac[prime[j]]%mod;
            if(i%prime[j]==0) break;
        }
    }
}
int main(){
    cin>>n;
    solve();
    ll ans=0;
    for(int i=1;i<=n;i++) ans^=fac[i];
    cout<<ans<<endl;
    return 0;
}

下面我们介绍一下线性筛求莫比乌斯函数

莫比乌斯函数
\(\mu(n)=\begin{cases} 1\qquad若n=1;\\(-1)^k 若n无平方因子数,且n=p_1*p_2....p_c;\\0 \qquad若n有平方因子数\end{cases}\)
显然\(\mu(n)\)是一个积性函数,那么如何用线性筛求出这个积性函数
我们考虑三种情况如下:
1.\(n=p_j^c\),那么有:\(\mu(p_j)=-1\),\(\mu(n)=0,c>1\)
2.\(n=i\times p_j\)\(p_j\mid i\),那么有:\(\mu(n)=0\)
3.\(n=i\times p_j\)\(p_j\nmid i\),那么有:\(\mu(n)=-\mu(i)\)

Code:

int prime[N],mu[N],vis[N],n,c;
void get_mu(){
    mu[1]=1;
	for(int i=2;i<N;i++){
		if(vis[i]==0){
			prime[c++]=i;
			mu[i]=-1;
		}
		for(int j=0;1LL*prime[j]*i<N;j++){
			vis[i*prime[j]]=1;
			if(i%prime[j]==0){
				mu[i*prime[j]]=0;
				break;
			}
			mu[i*prime[j]]=-mu[i];
		}
	}
}
posted @ 2021-12-14 16:37  Wraith-Fiee  阅读(64)  评论(0)    收藏  举报