51nod 1238 最小公倍数之和 V3
2017-06-12 17:18
344 查看
我们首先计算
f(n)===∑i=1nlcm(i,n)∑d|n∑i=1ndnidd[gcd(i,nd)=1]n∑d|nd⋅φ(d)+e(d)2
于是
==∑i=1nf(i)12∑d=1nd⋅φ(d)+e(d)∑i=1⌊nd⌋id12∑d=1nd2⋅φ(d)+e(d)∑i=1⌊nd⌋i
我们只需要杜教筛求出id2⋅φ的前缀和就可以了。
(id2⋅φ)×id2=id2⋅(φ×1)=id3
因此
=∑i=1ni2φ(i)∑i=1ni3−∑i=2ni2∑d=1⌊ni⌋d2φ(d)
求出f的前缀和之后不难得到答案。
f(n)===∑i=1nlcm(i,n)∑d|n∑i=1ndnidd[gcd(i,nd)=1]n∑d|nd⋅φ(d)+e(d)2
于是
==∑i=1nf(i)12∑d=1nd⋅φ(d)+e(d)∑i=1⌊nd⌋id12∑d=1nd2⋅φ(d)+e(d)∑i=1⌊nd⌋i
我们只需要杜教筛求出id2⋅φ的前缀和就可以了。
(id2⋅φ)×id2=id2⋅(φ×1)=id3
因此
=∑i=1ni2φ(i)∑i=1ni3−∑i=2ni2∑d=1⌊ni⌋d2φ(d)
求出f的前缀和之后不难得到答案。
#include<cstdio> #include<cmath> #include<algorithm> using namespace std; #define LL long long const int p=1000000007,maxn=5000010,mod=1000007,inv2=500000004,inv6=166666668; int phi[maxn],prm[maxn],sum[maxn],tot,m; LL n; /*void pause() { int x; x=1; }*/ int inc(int x,int y) { x+=y; return x>=p?x-p:x; } int dec(int x,int y) { x-=y; return x<0?x+p:x; } struct hashset { int fir[mod+10],ne[mod*5],ans[mod*5],tot; LL val[mod*5]; int find(LL n) { for (int i=fir[n%mod];i;i=ne[i]) if (val[i]==n) return ans[i]; return -1; } void ins(LL n,int x) { if (tot>mod*5-5) return; int y=n%mod; ne[++tot]=fir[y]; fir[y]=tot; val[tot]=n; ans[tot]=x; } }h; int sum1(LL n) { n%=p; return n*inc(n,1)%p*inv2%p; } int sum2(LL n) { n%=p; return n*inc(n,1)%p*inc(inc(n,n),1)%p*inv6%p; } int sum3(LL n) { int x=sum1(n); return (LL)x*x%p; } int calc(LL n) { if (n<=m) return sum ; int ret=h.find(n),ans,x,y; if (ret!=-1) return ret; ans=sum3(n); for (LL i=2,j;i<=n;i=j+1) { //if (n==10000000000LL&&j==3333333333LL) pause(); j=n/(n/i); x=dec(sum2(j),sum2(i-1)); y=calc(n/i); ans=dec(ans,(LL)x*y%p); //if (x<0||y<0||ans<0) printf("no:%lld,%lld,%lld\n",n,i,j); } h.ins(n,ans); return ans; } int main() { int ans=0,x,y; scanf("%lld",&n); m=pow(n,2.0/3); //m=100; phi[1]=sum[1]=1; for (int i=2;i<=m;i++) { if (!phi[i]) { prm[++tot]=i; phi[i]=i-1; } for (int j=1;j<=tot&&(LL)i*prm[j]<=m;j++) if (i%prm[j]) phi[i*prm[j]]=phi[i]*(prm[j]-1); else { phi[i*prm[j]]=phi[i]*prm[j]; break; } sum[i]=inc(sum[i-1],(LL)phi[i]*i%p*i%p); } for (LL i=1,j;i<=n;i=j+1) { j=n/(n/i); x=inc(dec(calc(j),calc(i-1)),i==1); y=sum1(n/i); ans=inc(ans,(LL)x*y%p); } printf("%d\n",dec(ans,sum1(n))); }
相关文章推荐
- [杜教筛] 51Nod 1238 最小公倍数之和 V3
- 51nod 1238 最小公倍数之和 V3
- 【51Nod 1238】最小公倍数之和 V3
- 51NOD 1238 最小公倍数之和 V3 [杜教筛]
- 51Nod-1238-最小公倍数之和 V3
- 51nod 1238 最小公倍数之和 V3 【欧拉函数+杜教筛】
- [数论][莫比乌斯反演][杜教筛] 51Nod 1238 最小公倍数之和 V3
- 【51NOD 1238】最小公倍数之和 V3
- 51Nod 最小公倍数之和V3
- 51 NOD 1238 最小公倍数之和 V3
- 【51nod】1238 最小公倍数之和 V3 杜教筛
- 51NOD 1227 平均最小公倍数 [杜教筛]
- 【51NOD 1222】最小公倍数计数
- 51Nod->1419最小公倍数挑战 (数论)
- [莫比乌斯反演 积性函数前缀和] 51Nod 1190 最小公倍数之和 V2
- 51nod 1227 平均最小公倍数【欧拉函数+杜教筛】
- 51Nod->1419最小公倍数挑战 (数论)
- 51nod 1190 最小公倍数之和V2
- [杜教筛] 51Nod 1227 平均最小公倍数
- 51nod 1190 最小公倍数之和 V2