orangejuice's blog
按ctrl会跳搜索,右上角选择day/night mode 似乎修好了搜索
测试中博客
HDU-5608
题意:$G(n)=n^2−3n+2=\sum_{d|n}F(d)$,求$\sum_1^nF(i)$
反演得到:$F(n)=\sum_{d|n}\mu(d)G(\frac{n} {d})$
则$\sum_1^nF(i)=\sum_i\sum_{d|i}\mu(d)G(\frac{i} {d})$
$\sum_1^nF(i)=\sum_{i=1}^{n}G(i)\sum_{j=1}^{\lfloor \frac{n} {i}\rfloor }\mu(j)$
问题就是要快速求$G(i)$前缀和和$\mu(i)$前缀和
第一个是$O(1)$求,第二个是杜教筛
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| const int N=5e6+10,P=1e9+7;
ll qpow(ll x,ll k=P-2) { ll res=1; for(;k;k>>=1,x=x*x%P) if(k&1) res=res*x%P; return res; }
const int Inv6=qpow(6);
int n; char notpri[N],w[N]; int pri[N/4],pc,Sw[N]; map <int,int> M;
int SumG(int n){ ll ans=1ll*n*(n+1)%P*(2*n+1)%P*Inv6%P; ans=(ans-3ll*n*(n+1)/2%P+2*n)%P; ans=(ans%P+P)%P; return ans; }
int Sumw(int n){ if(n<N) return Sw[n]; if(M.count(n)) return M[n]; int ans=1; for(int i=2,j;i<=n;i=j+1) { j=n/(n/i); ans-=(j-i+1)*Sumw(n/i); }
return M[n]=ans; }
int SumF(int n){ int ans=0; for(int i=1,j;i<=n;i=j+1) { j=n/(n/i); ans=(ans+1ll*(SumG(j)-SumG(i-1))*Sumw(n/i))%P; } ans=(ans%P+P)%P; return ans; }
int main(){ w[1]=1; rep(i,2,N-1) { if(!notpri[i]) pri[++pc]=i,w[i]=-1; for(int j=1;j<=pc && 1ll*i*pri[j]<N;++j) { notpri[i*pri[j]]=1; if(i%pri[j]==0) { w[i*pri[j]]=0; break; } w[i*pri[j]]=-w[i]; } } rep(i,1,N-1) Sw[i]=Sw[i-1]+w[i]; rep(kase,1,rd()) printf("%d\n",SumF(rd())); }
|
本文代表个人观点,内容仅供参考。若有不恰当之处,望不吝赐教!