Farey Sequence
傳送門
題意:
寫在前面
繼續補1月份的題,才發現這道題這麼簡單,果然當時的我太菜了。(當然現在的我也很菜…。)
思路
看到,我們仔細觀察,會發現,答案就是歐拉函數的前綴和。爲什麼呢?發現F4比起F3,不就是多出來了,有關於4的,從1到4數的,gcd=1的個數嗎?再看看歐拉函數的定義,小於等於n與n互質的個數。
求歐拉函數的前綴和,我會的有三種方法:
(1)線性篩出歐拉函數,老老實實O(n)求前綴和(這可能也是這道題的標準作法,因爲這道題就是道水題)。
(2)杜教篩
(3)通過莫比烏斯反演來求,要藉助莫比烏斯函數,所以已經求出了莫比烏斯函數前綴和時這樣做最快。時間複雜度。
線性篩
首先我們回憶一下線性篩模板:
原理:每個合數都被其最小質因子篩去。
void init(){
for(int i=2;i<maxn;i++){
if(!vis[i]) pri[cnt++]=i;
for(int j=0;j<cnt&&1ll*i*pri[j]<maxn;j++){
vis[i*pri[j]]=1;
//break是因爲這個i被pri[j]與之前的某個i篩過了
//如果i再與其他質數相乘
//得到的值早就被這個pri[j]篩過
if(i%pri[j]==0) break;
}
}
}
求歐拉函數的線性篩:
原理:
直接套定義:。每個數一開始爲n,後來被其因子更新。
void get_phi(int n) {
phi[1]=1;
for(int i=2;i<=n;i++)
if(!phi[i])
for(int j=i;j<=n;j+=i) {
if(!phi[j]) phi[j]=j;
phi[j]=phi[j]/i*(i-1);
}
}
同時求質數的線性篩:
原理:
設是的最小質因子,,線性篩的過程中,被篩掉。按照歐拉篩(線性篩)的套路,我們會面對兩種情況:和。
性質1:
如果,此時與互質,那麼(積性函數)
性質2:
如果,此時包含了的所有因子,所以
即
就等價於(因爲注意後面的fraction不考慮質因子的冪次)
void init(){
for(int i=2;i<maxn;i++){
if(!vis[i]){
phi[i]=i-1;
pri[cnt++]=i;
}
for(int j=0;j<cnt&&1ll*pri[j]*i<maxn;j++){
vis[i*pri[j]]=1;
if(i%pri[j])
phi[i*pri[j]]=phi[i]*(pri[j]-1);//性質1
else {
phi[i*pri[j]]=phi[i]*pri[j];//性質2
break;
}
}
}
}
好了,那我們就選擇定義求歐拉函數的線性篩法來做題。
代碼:
#include<stdio.h>
typedef long long ll;
ll phi[1000005],sum[1000005];
void get_phi(ll n) {
phi[1]=0;
for(ll i=2;i<=n;i++)
if(!phi[i])
for(ll j=i;j<=n;j+=i) {
if(!phi[j]) phi[j]=j;
phi[j]=phi[j]/i*(i-1);
}
}
int main(){
get_phi(1000000);
for(ll i=1;i<=1000000;i++){
sum[i]=sum[i-1]+phi[i];
}
ll n;
while(~scanf("%lld",&n)&&n){
printf("%lld\n",sum[n]);
}
}
杜教篩
求。
根據Dirichlet卷積:。
我們有,(函數即)(證明見下)
(ATTENTION:先坑了抱歉,期末複習了)
莫比烏斯反演
知識傳送門
由文字定義可知,歐拉函數就是,那麼歐拉函數的前綴和其實就是。(前綴和嘛,外面多累加一次)。由莫比烏斯函數的性質,我們得到。
我們稍作變換,得到。
涉及知識
歐拉函數
定義
性質
單個求值(定義)
線性篩
見上。
前綴和
見上。