51nod1244(杜教筛)

杜教筛实在是太神了。。有关杜教筛可参考tls文章:https://blog.csdn.net/skywalkert/article/details/50500009

针对这题来说,设莫比乌斯函数为M(n),由\sum_{d|n}\mu(d)=e(n),可做如下化简:

M(n)=\sum_{i=1}^{n}\mu(i)=\sum_{i=1}^{n}(e(i)-\sum_{d|i\&\&d<i}\mu(d)) =1-\sum_{i=1}^{n}\sum_{d|n\&\&d<n}\mu(d)

枚举倍数d的倍数,由于对一个d,其累加次数为n/d次,即倍数为i的d最大为n/d,故有下式

M(n)=1-\sum_{i=1}^{n} \sum_{d=1}^{\left \lfloor \frac{n}{i} \right \rfloor}\mu(d)=1-\sum_{i=1}^{n}M(\left \lfloor \frac{n}{i} \right \rfloor)

然后上式可分块求,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));
}

 

 

 

 

1244 莫比乌斯函数之和

基准时间限制: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
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值