【BZOJ4916】神犇和蒟蒻 杜教筛

题目传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4916

第一个询问即求出$\sum_{i=1}^{n} { \mu (i^2)} $,考虑到$\mu$的定义,当i>1时必存在次数为偶数的质因子,故在数据范围内,$\sum_{i=1}^{n} { \mu (i^2)} $恒等于1。

第二个询问即求出$\sum_{i=1}^{n} { \varphi  (i^2)} $,考虑到$\varphi$的定义,则有$\varphi(i^2)=i\times \varphi(i)$。

问题转化为求$\sum_{i=1}^{n} { i\times \varphi  (i)} $

下面开始化简式子,考虑式子$n=\sum_{i|n}{\varphi (i)}$

通过简单变式,得:$n=\sum_{i|n\&i<n}{\varphi (i)}+\varphi (n)$

移项,得:$\varphi (n)=n-\sum_{i|n\&i<n}{\varphi (i)}$

通过之前推出的式子,得:$\mu(n^2)=n^2-n\times\sum_{i|n\&i<n}{\mu(i)}$

我们设$\Phi(n)=\sum_{i=1}^{n} { \varphi  (i^2)}$

则:

$\Phi(n)=\sum_{i=1}^{n} (i^2-i \times \sum_{j|i\&j<i}\varphi(j))$

$=\frac{n(n+1)(2n+1)}{6}-\sum_{i=1}^{n} i \times \sum_{j|i\&j<i}\varphi(j)$

$=\frac{n(n+1)(2n+1)}{6}-\sum_{i=2}^{n} i \times \sum_{j=1}^{\left \lfloor \frac{n}{i} \right \rfloor}\varphi(j)\times j$

$=\frac{n(n+1)(2n+1)}{6}-\sum_{i=2}^{n} i \times \Phi(\left \lfloor \frac{n}{i} \right \rfloor)$

然后用杜教筛的思路+预处理1~19260817的$i\times \mu (i)$的前缀和即可

 

 1 #include<bits/stdc++.h>
 2 #define L long long
 3 #define M 19260817
 4 #define MOD 1000000007
 5 #define inv6 166666668
 6 using namespace std;
 7 
 8 int b[M]={0},phi[M]={0},use=0; L pri[M]={0};
 9 void init(){
10     phi[1]=1;
11     for(int i=2;i<M;i++){
12         if(!b[i]) pri[++use]=i,phi[i]=i-1;
13         for(int j=1;j<=use&&i*pri[j]<M;j++){
14             b[i*pri[j]]=1; 
15             if(i%pri[j]==0) {phi[i*pri[j]]=phi[i]*pri[j]; break;}
16             phi[i*pri[j]]=phi[i]*(pri[j]-1);
17         }
18     }
19     for(L i=1;i<M;i++) phi[i]=(phi[i-1]+phi[i]*i)%MOD;
20 }
21 
22 map<int,L> mp;
23 L solve(L n){
24     if(n<M) return phi[n];
25     if(mp[n]) return mp[n];
26     L pls=n*(n+1)%MOD*(n<<1|1)%MOD*inv6%MOD,ans=0;
27     for(L i=2,j;i<=n;i=j+1){
28         j=n/(n/i);
29         L sumi=((i+j)*(j-i+1)/2)%MOD;
30         ans=(ans+solve(n/i)%MOD*sumi)%MOD;
31     }
32     ans=(pls-ans+MOD)%MOD;
33     return mp[n]=ans;
34 }
35 
36 int main(){
37     init();
38     int n; scanf("%d",&n); printf("1\n");
39     printf("%lld\n",solve(n));
40 }

 

posted @ 2018-02-27 21:14  AlphaInf  阅读(213)  评论(0编辑  收藏  举报