杜教筛实在是太神了。。有关杜教筛可参考tls文章:https://blog.youkuaiyun.com/skywalkert/article/details/50500009
针对这题来说,设莫比乌斯函数为M(n),由,可做如下化简:
枚举倍数d的倍数,由于对一个d,其累加次数为n/d次,即倍数为i的d最大为n/d,故有下式
然后上式可分块求,tls文章里面分析复杂度为O(n^(3/4)),如果预处理前n^(2/3)复杂度可降至O(n^(2/3)),然而窝并不会证。。
然后不用map存中间变量就特别慢,窝也不造为什么。。所以实际复杂度可能多一个log。。
/**
* ┏┓ ┏┓
* ┏┛┗━━━━━━━┛┗━━━┓
* ┃ ┃
* ┃ ━ ┃
* ┃ > < ┃
* ┃ ┃
* ┃... ⌒ ... ┃
* ┃ ┃
* ┗━┓ ┏━┛
* ┃ ┃ Code is far away from bug with the animal protecting
* ┃ ┃ 神兽保佑,代码无bug
* ┃ ┃
* ┃ ┃
* ┃ ┃
* ┃ ┃
* ┃ ┗━━━┓
* ┃ ┣┓
* ┃ ┏┛
* ┗┓┓┏━━━━━━━━┳┓┏┛
* ┃┫┫ ┃┫┫
* ┗┻┛ ┗┻┛
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<set>
#include<bitset>
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,l,r) for(int i=l;i>=r;i--)
#define link(x) for(edge *j=h[x];j;j=j->next)
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define eps 1e-8
#define succ(x) (1LL<<(x))
#define lowbit(x) (x&(-x))
#define sqr(x) ((x)*(x))
#define mid (x+y>>1)
#define NM 5000005
#define nm 200005
#define N 1000005
#define M(x,y) x=max(x,y)
const double pi=acos(-1);
const ll inf=1e9+7;
using namespace std;
ll read(){
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return f*x;
}
int mu[NM],a[NM],tot,prime[NM],n;
ll _x,_y;
bool v[NM];
map<ll,ll>b;
void init(){
n=5e6;mu[1]=a[1]=1;
inc(i,2,n){
if(!v[i])prime[++tot]=i,mu[i]=-1;
inc(j,1,tot){
if(i*prime[j]>n)break;
v[i*prime[j]]++;
if(i%prime[j]==0)break;
mu[i*prime[j]]=-mu[i];
}
a[i]=a[i-1]+mu[i];
}
}
ll Mu(ll m){
if(m<=n)return a[m];
if(b[m])return b[m];
ll s=0;
for(ll x=2,y;x<=m;x=y+1){
y=m/(m/x);
s+=(y-x+1)*Mu(m/x);
}
b[m]=1-s;
return b[m];
}
int main(){
init();
_x=read();_y=read();
printf("%lld\n",Mu(_y)-Mu(_x-1));
}
基准时间限制:3 秒 空间限制:131072 KB 分值: 320 难度:7级算法题
收藏
关注
莫比乌斯函数,由德国数学家和天文学家莫比乌斯提出。梅滕斯(Mertens)首先使用μ(n)(miu(n))作为莫比乌斯函数的记号。具体定义如下:
如果一个数包含平方因子,那么miu(n) = 0。例如:miu(4), miu(12), miu(18) = 0。
如果一个数不包含平方因子,并且有k个不同的质因子,那么miu(n) = (-1)^k。例如:miu(2), miu(3), miu(30) = -1,miu(1), miu(6), miu(10) = 1。
给出一个区间[a,b],S(a,b) = miu(a) + miu(a + 1) + ...... miu(b)。
例如:S(3, 10) = miu(3) + miu(4) + miu(5) + miu(6) + miu(7) + miu(8) + miu(9) + miu(10)
= -1 + 0 + -1 + 1 + -1 + 0 + 0 + 1 = -1。
Input
输入包括两个数a, b,中间用空格分隔(2 <= a <= b <= 10^10)
Output
输出S(a, b)。
Input示例
3 10
Output示例
-1