[NOI.AC WC模拟赛五]A(杜教筛)

http://noi.ac/problem/23

$$\begin{align*}
&\ \ \ \ \sum_{k=1}^{n}\sum_{i=1}^{k}\sum_{j=1}^{k}(i,j,k)\\
&=\sum_{p=1}^{n}p\sum_{k=1}^{\lfloor\frac{n}{p}\rfloor}\sum_{i=1}^{k}\sum_{j=1}^{k}[(i,j,k)=1]\\
&=\sum_{p=1}^{n}p\sum_{k=1}^{\lfloor\frac{n}{p}\rfloor}\sum_{i=1}^{k}\sum_{j=1}^{k}\sum_{d|i,d|j,d|k}\mu(d)\\
&=\sum_{p=1}^{n}p\sum_{d=1}^{\lfloor\frac{n}{p}\rfloor}\mu(d)\sum_{k=1}^{\lfloor\frac{n}{pd}\rfloor}\sum_{i=1}^{k}\sum_{j=1}^{k}1\\
&=\sum_{p=1}^{n}p\sum_{d=1}^{\lfloor\frac{n}{p}\rfloor}\mu(d)f(\lfloor\frac{n}{pd}\rfloor)\\
&=\sum_{T=1}^{n}f(\lfloor\frac{n}{T}\rfloor)\sum_{d|T}\mu(d)\cdot\frac{T}{d}\\
&=\sum_{T=1}^{n}f(\lfloor\frac{n}{T}\rfloor)\varphi(T)
\end{align*}$$

其中$f(n)=\sum_{i=1}^{n}i^2=\frac{n(n+1)(2n+1)}{6}$,最后一步是根据$id*\mu=\varphi$得到的。
观察这个式子发现可以根号加速,$\varphi$的前缀和用杜教筛求出。通过记忆化能做到玄学复杂度。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 5 using namespace std;
 6 
 7 const int N=1000010;
 8 int n,mod,m=1000000,inv,b[N],p[N],tot,phi[N],Phi[N],ans;
 9 
10 int ksm(int a,int b){
11     int res=1;
12     for (; b; a=1ll*a*a%mod,b>>=1)
13         if (b & 1) res=1ll*res*a%mod;
14     return res;
15 }
16 
17 int S(int x){ return 1ll*x*(x+1)%mod*(x+x+1)%mod*inv%mod; }
18 
19 void init(int n){
20     rep(i,2,n){
21         if (!b[i]) p[++tot]=i,phi[i]=i-1;
22         for (int j=1; i*p[j]<=n; ++j){
23             b[i*p[j]]=1;
24             if (i%p[j]) phi[i*p[j]]=phi[i]*(p[j]-1);
25                 else { phi[i*p[j]]=phi[i]*p[j]; break; }
26         }
27     }
28 }
29 
30 int P(int x){
31     if (x<=m) return phi[x];
32     if (~Phi[n/x]) return Phi[n/x];
33     int res=0;
34     for (int i=2,j; i<=x; i=j+1)
35         j=x/(x/i),res=(res+1ll*(j-i+1)*P(x/i))%mod;
36     res=((1ll*x*(x+1)>>1)-res+mod)%mod;
37     return Phi[n/x]=res;
38 }
39 
40 int main(){
41     freopen("a.in","r",stdin);
42     freopen("a.out","w",stdout);
43     scanf("%d%d",&n,&mod); inv=ksm(6,mod-2); phi[1]=1; init(m);
44     rep(i,1,m) phi[i]=(phi[i]+phi[i-1])%mod;
45     memset(Phi,-1,sizeof(Phi));
46     for (int i=1,j; i<=n; i=j+1)
47         j=n/(n/i),ans=(ans+1ll*(P(j)-P(i-1)+mod)*S(n/i))%mod;
48     printf("%d\n",ans);
49     return 0;
50 }

猜你喜欢

转载自www.cnblogs.com/HocRiser/p/10227119.html
今日推荐