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:先坑了抱歉,期末复习了)
莫比乌斯反演
知识传送门
由文字定义可知,欧拉函数就是,那么欧拉函数的前缀和其实就是。(前缀和嘛,外面多累加一次)。由莫比乌斯函数的性质,我们得到。
我们稍作变换,得到。
涉及知识
欧拉函数
定义
性质
单个求值(定义)
线性筛
见上。
前缀和
见上。