51nod1584:加权约数和 (莫比乌斯反演)
来源:互联网 发布:音乐截取软件 编辑:程序博客网 时间:2024/05/19 11:47
题目传送门:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1584
题目分析:这题应该算是[SDOI2015]约数个数和的加强版吧,如果还没有做过这道题的同学可以先想一想这题。至于它的解法你们可以自行百度(或看看我写的题解)
好吧,回到这题。
我们要搞清楚一个东西:
在[SDOI2015]约数个数和这题中,我们有一个很巧妙的公式:
很明显,我们发现表格中1的个数刚好就是
现在我们要求的是
这样我们就看得很清楚了,我们要求的是
以上就是我在草稿纸上自己YY的过程,后来我才知道就是这样做的。
然后我们把这个式子带进原题中,基本上就求解了。
说实话,在我写这篇总结之前,网上已经有大神给出了十分优秀的题解,但鉴于这提示本人自己推导的,我还是将自己的推导过程写在下面,以作纪念吧。
题目要求:
我们发现这个max很讨厌,于是令j只枚举到i,变形成:
其中右边是要减去重复计算的ans(i,i),这一部分用线性筛后再做一次前缀和即可O(1)得到。线性筛时若i%prime[j]!=0,直接用积性函数的性质
然后考虑左边2后面那一坨,转化成:
将x,y的枚举拉到i,j前面,重新令
然后我们将k的枚举拉到最前面,重新令
我们记
对F函数做前缀和,就可以做到预处理O(n),询问O(
式子推到上面我就推不下去了,感觉没办法让时间更优。
后来上网看了看别人的题解,原来再换个枚举顺序就可以了……(我是智障)
记d=i*k,外层枚举d,得到:
然后就变成了预处理O(n*ln(n)),询问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=1000010;const long long M=1000000007;typedef long long LL;int pk[maxn];LL h[maxn];LL p[maxn];LL mu[maxn];bool vis[maxn];int prime[maxn];int cur=0;LL g[maxn];LL f[maxn];int t,n;void Preparation(){ h[1]=p[1]=mu[1]=1; for (int i=2; i<maxn; i++) { if (!vis[i]) pk[i]=i,h[i]=i+1,p[i]=i,p[i]*=i,p[i]=(p[i]+i+1)%M,mu[i]=-1,prime[++cur]=i; for (int j=1; j<=cur && i*prime[j]<maxn; j++) { int k=i*prime[j]; vis[k]=true; if (i%prime[j]) pk[k]=prime[j],h[k]=h[i]*h[ pk[k] ],p[k]=p[i]*p[ pk[k] ]%M,mu[k]=-mu[i]; else { pk[k]=pk[i]*prime[j]; h[k]=h[i]+h[ i/pk[i] ]*pk[k]; p[k]=pk[i]+pk[k],p[k]=p[k]*pk[k]%M*p[ i/pk[i] ]%M,p[k]=(p[k]+p[i])%M; mu[k]=0; break; } } } for (int i=1; i<maxn; i++) p[i]=p[i]*i%M; for (int i=2; i<maxn; i++) p[i]=(p[i]+p[i-1])%M; for (int i=1; i<maxn; i++) mu[i]=(mu[i]+M)*i%M*i%M; g[1]=1; for (int i=2; i<maxn; i++) g[i]=(g[i-1]+h[i])%M; for (int i=1; i<maxn; i++) g[i]=g[i]*i%M*h[i]%M; for (int i=1; i<maxn; i++) for (int j=1; i*j<maxn; j++) f[i*j]=(f[i*j]+ mu[i]*g[j]%M )%M; for (int i=2; i<maxn; i++) f[i]=(f[i]+f[i-1])%M;}int main(){ freopen("c.in","r",stdin); freopen("c.out","w",stdout); Preparation(); scanf("%d",&t); for (int i=1; i<=t; i++) { scanf("%d",&n); LL ans=(f[n]*2LL-p[n]+M)%M; printf("Case #%d: %lld\n",i,ans); } return 0;}
- [莫比乌斯反演] 51nod1584. 加权约数和
- 51nod1584:加权约数和 (莫比乌斯反演)
- 51nod1584 加权约数和
- [莫比乌斯反演] 51Nod 1584 加权约数和
- 51nod1584:加权约数和(数论+线性筛)
- 【莫比乌斯反演】[BZOJ3994]约数个数和
- Sdoi2015约数个数和题解莫比乌斯反演
- bzoj3994 约数个数和 数论&莫比乌斯反演
- 【bzoj3994】[SDOI2015]约数个数和 莫比乌斯反演
- 3994: [SDOI2015]约数个数和 莫比乌斯反演
- 约数个数和(数论,莫比乌斯反演)BZOJ3994
- BZOJ 3994 约数个数和(莫比乌斯反演)
- [莫比乌斯反演 约数个数] BZOJ 3994 [SDOI2015]约数个数和
- [BZOJ3994][SDOI2015]约数个数和(莫比乌斯反演)
- 【BZOJ3994】【SDOI2015】约数个数和(莫比乌斯反演)
- 洛谷P3327:[SDOI2015]约数个数和 (莫比乌斯反演)
- [BZOJ3994][SDOI2015]约数个数和(莫比乌斯反演)
- [BZOJ3994][SDOI2015]约数个数和(莫比乌斯反演)
- Eclipse插件开发(三)插件的代码开发
- 字符串处理技术之格式化字符串(字符串大小写转换)
- leetcode 41. First Missing Positive
- 区块链开发专题(数字货币分叉、矿池、共识攻击)
- 字符串处理技术之格式化字符串(字符与Unicode码的转换)
- 51nod1584:加权约数和 (莫比乌斯反演)
- 最新Hyperledger fabric 1.0 bate版ubuntu安装 配置 测试
- Qt基础 11_布局管理
- 前端开发app,关于apicloud与dcloud的我的一些看法
- 汇编语言(第三版)实验1-17
- C白白的游戏服务器开发笔记:安装linux下c的开发环境
- 斐波那契数列-java基础
- mac配置python
- MySQL--字符函数