OPPO F21 曝光:預計搭載聯發科 Helio P95,64MP 後置四攝
先開始第一個問題:求正整數\(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];
}
}
}