您的位置:首页 > 其它

[莫比乌斯反演 复杂度分析] 51Nod 1222 最小公倍数计数

2017-01-26 23:15 393 查看


这么反演一通

转化为abc<=n的解数 [暴力]
HDU 4473 Exam 

a 以立方根的复杂度枚举一通再讨论下就好了

既然糖老师强调复杂度分析 那就来分析分析

对于子问题  abc<=n

复杂度是n的2/3次的

再套一重外循环是n的5/6次?

肯定是我分析错了

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include <tr1/unordered_map>
typedef long long ll;
using namespace std;
using namespace std::tr1;

const int maxn=10000000;

int prime[1000000],num;
int vst[maxn+5],miu[maxn+5];

inline void Pre(){
miu[1]=1;
for (int i=2;i<=maxn;i++){
if (!vst[i]) prime[++num]=i,miu[i]=-1;
for (int j=1;j<=num && (ll)i*prime[j]<=maxn;j++){
vst[i*prime[j]]=1;
if (i%prime[j]==0){
miu[i*prime[j]]=0;
break;
}
miu[i*prime[j]]=miu[i]*miu[prime[j]];
}
}
}

inline ll calc(ll n){
ll ans=0;
for(ll a=1;a*a*a<=n;a++)
for(ll b=a;a*b*b<=n;b++){
ll c=n/(a*b);
if(c<b) break;
if(a==b)
ans+=(c-b)*3+1;
else
ans+=(c-b)*6+3;
}
return ans;
}

inline ll Solve(ll n){
if (!n) return 0;
ll ret=0;
for (ll k=1;k*k<=n;k++)
if (miu[k])
ret+=miu[k]*calc(n/k/k);
ret=(ret+n)/2;
return ret;
}

int main(){
ll l,r;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
scanf("%lld%lld",&l,&r); Pre();
printf("%lld\n",Solve(r)-Solve(l-1));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: