SPOJ DIVCNT2(莫比乌斯反演+杜教筛)
来源:互联网 发布:yy mac版 编辑:程序博客网 时间:2024/06/08 16:30
题目传送门:http://www.spoj.com/problems/DIVCNT2/
题目分析:
千古神题,这题想了我两天也没想出来……
好吧,其实这题并没有用杜教筛,它并没有使用记忆化递归,也没有用狄利克雷卷积,只不过它的时间复杂度证明和杜教筛类似,也是
回到正文:
题目要我们求:
相当于求:
如果我们改为先枚举d,接下来我们还要枚举一层什么呢?我们很容易发现,假设:
那么它能够贡献的最小的i就是:
同时,h(d)的平方以及它的倍数的平方也会被d更新到。
于是,原式变为:
然后我们再改一下枚举的顺序,我们令j=h(d),那么当我们枚举j的时候,有多少个d会满足要求呢?我们分析一下,设:
则满足h(d)=j的d为:
(-1)表示可以减一,也可以不减。
于是我们就发现了,满足条件的d有
于是原式化成:
然而这还是不可做,我们又发现,
我们令
然后我们记右边的值为
我们同时还发现:F(n)本质上就是1~n中无平方因子的数的个数,我们要求单独的一个F(n),可以通过一个
至于还不知道为什么的同学可以去看看这题:bzoj2440完全平方数。
而我们知道,单独求一个G(n)也是可以用
而且我们可以用线性筛在O(n)的时间内求出1~n的所有F值(求个
现在我们看回原式:
我们对G进行下底函数分块,假设
之前说过,我们可以通过预处理达到O(1)返回这三个值,也可以用
CODE:
#include<iostream>#include<string>#include<cstring>#include<cmath>#include<cstdio>#include<cstdlib>#include<stdio.h>#include<algorithm>using namespace std;const int maxn=1e8;const int maxt=10010;typedef long long LL;bool vis[maxn];int prime[maxn/10];int cur=0;int miu[maxn];LL f[maxn];int pk[maxn];LL g[maxn];LL que[maxt];int t;LL n=0,N;void Preparation(){ miu[1]=1,g[1]=1; for (int i=2; i<N; i++) { if (!vis[i]) prime[++cur]=i,miu[i]=-1,pk[i]=1,g[i]=2; for (int j=1; j<=cur && i*prime[j]<N; j++) { int k=i*prime[j]; vis[k]=true; if (i%prime[j]) miu[k]=-miu[i],pk[k]=1,g[k]=2*g[i]; else { miu[k]=0; pk[k]=pk[i]+1; g[k]=g[i]/pk[k]*(pk[k]+1); break; } } } for (int i=1; i<N; i++) f[i]=miu[i]*miu[i]; for (int i=2; i<N; i++) f[i]+=f[i-1],g[i]+=g[i-1];}LL G(LL x){ if (x<N) return g[x]; LL temp=0,last; for (LL i=1; i<=x; i=last+1) { last=x/(x/i); temp+=( x/i*(last-i+1LL) ); } return temp;}LL F(LL x){ if (x<N) return f[x]; int sx=(int)floor( sqrt( (double)x )+0.0000001 ); LL temp=0; for (int i=1; i<=sx; i++) temp+=( (long long)miu[i]*( x/( (long long)i*(long long)i ) ) ); return temp;}int main(){ freopen("c.in","r",stdin); freopen("c.out","w",stdout); scanf("%d",&t); for (int i=1; i<=t; i++) { cin>>que[i]; n=max(n,que[i]); } if (n<=10000) N=n+1; else N=maxn; Preparation(); for (int q=1; q<=t; q++) { n=que[q]; LL ans=0,last; for (LL i=1; i<=n; i=last+1) { last=n/(n/i); ans+=( G(n/i)*( F(last)-F(i-1) ) ); } cout<<ans<<endl; } return 0;}
阅读全文
1 0
- SPOJ DIVCNT2(莫比乌斯反演+杜教筛)
- spoj 4491 莫比乌斯反演
- SPOJ VLATTICE(莫比乌斯反演)
- spoj 7001. Visible Lattice Points(莫比乌斯反演)
- zoj 3435 spoj 7001 莫比乌斯反演
- SPOJ VLATTICE - Visible Lattice Points 莫比乌斯反演
- SPOJ 7001. Visible Lattice Points (莫比乌斯反演)
- SPOJ 7001 Visible Lattice Points (莫比乌斯反演)
- 【莫比乌斯反演】[SPOJ-VLATTICE]Visible Lattice Points
- 【莫比乌斯反演】[SPOJ VLATTICE]Visible Lattice Points
- SPOJ VLATTICE Visible Lattice Points - 莫比乌斯反演
- SPOJ 7001. Visible Lattice Points 莫比乌斯反演
- SPOJ 7001 VLATTICE【莫比乌斯反演】
- 莫比乌斯反演1003 SPOJ VLATTICE
- SPOJ 7001 Visible Lattice Points (莫比乌斯反演)
- SPOJ 7001 Visible Lattice Points(莫比乌斯反演)
- spoj Primes in GCD Table 莫比乌斯反演
- spoj 7001 zoj 3435 莫比乌斯反演
- Spring学习笔记之保护方法应用
- [杜教筛] BZOJ 4916 神犇和蒟蒻
- 剑指offer-合法的出栈序列
- 38 C语言自增(++)和自减(--)
- 微博分享sdk4.0 中遇到的坑以及解决办法汇总
- SPOJ DIVCNT2(莫比乌斯反演+杜教筛)
- 在微服务的世界里, 你应该要知道的几件事
- 数据库复习(1)--MySQL复制表结构和数据
- Linux脚本学习攻略笔记16
- 指针与引用的比较
- Mecanim动画系统学习(一)
- NTP服务器配置
- mysql 删除表中重复的数据,只保留一条
- 个人认为安卓开发前景