【51Nod1244】莫比烏斯函式之和
阿新 • • 發佈:2019-02-11
Description
莫比烏斯函式,由德國數學家和天文學家莫比烏斯提出。梅滕斯(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。
Solution
先寫出表示式
設
所以
一開始不知道怎麼辦。。。但是突然想到了一個東西。
發現了求和性質和1的這個特殊性。
熟練掌握內層外移的話,這種東西只可以轉化的。
這個式子=
再帶入f陣列轉化一下。
這個式子=
因為
所以
然後再分塊一下。
會超時!
打一個記憶化搜尋。像模擬連結串列一樣。
注意!
空間不要都要long long,會爆啊!
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define rep(i,a) for(i=first[a];i;i=next[i])
using namespace std;
typedef long long ll;
const int maxn=5000007 ,mo=857777;
int i,j,k,l,t,n,m,miu[maxn],p[maxn],sum[maxn];
ll a,b,ans,chang[mo];
int next[mo],last[mo],first[mo],num;
bool bz[maxn];
void add(int x,int y,ll z){
last[++num]=y;next[num]=first[x];first[x]=num;chang[num]=z;
}
int suan(ll x){
int i,j=x%mo,k=1;ll l=2,r;
if(x<=maxn)return sum[x];
rep(i,j)if(last[i]==x)return chang[i];
while(l<=x){
r=x/(x/l);
k-=(r-l+1)*suan(x/l);
l=r+1;
}
add(j,x,k);
return k;
}
int main(){
scanf("%lld%lld",&a,&b);
miu[1]=1;
fo(i,2,maxn){
if(!bz[i]){
miu[i]=-1;
p[++p[0]]=i;
}
fo(j,1,p[0]){
t=i*p[j];if(t>maxn)break;bz[t]=1;
if(!(i%p[j])){break;}
miu[t]=-miu[i];
}
}
fo(i,1,maxn)sum[i]=sum[i-1]+miu[i];
printf("%d",suan(b)-suan(a-1));
}