zoukankan      html  css  js  c++  java
  • 【GDKOI2017】小队任务 莫比乌斯反演+杜教筛

    题目大意:给你n,求$sum_{i=1}^{n}sum_{j=i}^{n}[gcd(i,j)=1](i+1)(j+1)$

    子任务一:暴力

    子任务二:$T=50000,n≤10^7$

    子任务三:$T=3,n≤10^{10}$

     

    解法一:

    我们化一下这个式子

    $sum_{i=1}^{n}sum_{j=i}^{n}[gcd(i,j)=1](i+1)(j+1)$

    $=sum_{i=1}^{n}sum_{j=i}^{n}sum_{k|gcd(i,j)} mu(k)(i+1)(j+1)$

    $=frac{1}{2}igg(4+sum_{d=1}^{n}sum_{i=1}^{Q}sum_{j=1}^{Q}(di+1)(dj+1)igg)$其中$Q=lfloor frac{n}{d} floor $,下面同理

    $=frac{1}{2}igg(4+sum_{d=1}^{n}mu(d)(Q^2+d(1+Q)Q^2+d^2(frac{(1+Q)Q}{2})^2)igg)$

    不难发现,这个式子可以预处理出$mu(i)$的前缀和,然后通过根号分块的方法,实现单次$O(sqrt{n})$时间复杂度的询问操作。在前两个子任务中,时间复杂度为$O(Tsqrt{n})$。

    在第三个子任务中,我们采用杜教筛求$mu$的前缀和,即可实现求得答案。

    但是问题在于,该题单点的时限为15s,本蒟蒻经过大力卡常后,第二个子任务依然只能在17s左右跑出。

     

    我们考虑换一个做法,还是刚才的式子

    $sum_{i=1}^{n}sum_{j=i}^{n}[gcd(i,j)=1](i+1)(j+1)$

    考虑到要让$gcd(i,j)=1$,那么在i不变的情况下,共有$varphi(i)$个数,它们的和为$frac{1}{2}i imes varphi(i)$。

    那么原式为:

    $=frac{1}{2}sum_{i=1}^{n}(i+1)(i+2)varphi(i)$

    $=frac{1}{2}sum_{i=1}^{n}igg(2(i+1)varphi(i)+i(i+1)varphi(i) igg)$

    $=frac{1}{2}igg( 2sum_{i=1}^{n}varphi(i)+3sum_{i=1}^{n}ivarphi(i)+sum_{i=1}^{n}i^2varphi(i) igg)$

    该式子,我们可以预处理出$varphi(i)$,$ivarphi(i)$,$i^2varphi(i)$的前缀和,那么当n≤10^7时,可以实现O(1)求得答案

    对于第三个子任务,$n≤10^{10}$,显然不可以预处理到$10^{10}$,求$varphi(i)$,$ivarphi(i)$,$i^2varphi(i)$的前缀和,我们可以通过杜教筛+预处理实现$O(n^{frac{2}{3}})$的单次询问,可以通过第三个子任务。

    杜教筛部分详见代码,在此不再展开。

    完结撒花

     1 #include<bits/stdc++.h>
     2 #define L long long
     3 #define MOD 1000000007
     4 #define I2  500000004
     5 #define I6  166666668
     6 #define M 19890604
     7 using namespace std;
     8 int pri[M/10]={0},b[M]={0},use=0;
     9 int phi[M][3]={0};
    10 
    11 L get(L n,L op){
    12     n%=MOD;
    13     if(op==0) return n;
    14     if(op==1) return ((1+n)*n/2)%MOD;
    15     if(op==2) return n*(n+1)%MOD*(2*n+1)%MOD*I6%MOD;
    16     n=(n*(n+1)/2)%MOD; return n*n%MOD;
    17 }
    18 map<L,L> mp[3];
    19 L PHI(L n,L k){
    20     if(n<M) return phi[n][k];
    21     if(mp[k][n]) return mp[k][n];
    22     L res=get(n,k+1);
    23     for(L i=2,j;i<=n;i=j+1){
    24         j=n/(n/i);
    25         res=(res-(get(j,k)-get(i-1,k))*PHI(n/i,k))%MOD;
    26     }
    27     return mp[k][n]=res;
    28 }
    29 
    30 L Main(){
    31     L n; scanf("%lld",&n);
    32     L p1=PHI(n,0),p2=PHI(n,1),p3=PHI(n,2);
    33     L ans=(p1*2+p2*3+p3)%MOD*I2%MOD;
    34     printf("%lld
    ",(ans+1+MOD)%MOD);
    35 }
    36 
    37 int main(){
    38     phi[1][0]=phi[1][1]=phi[1][2]=1;
    39     for(L i=2;i<M;i++){
    40         if(b[i]==0) pri[++use]=i,phi[i][0]=i-1;
    41         for(L j=1;j<=use&&i*pri[j]<M;j++){
    42             b[i*pri[j]]=1;
    43             if(i%pri[j]==0){phi[i*pri[j]][0]=phi[i][0]*pri[j]; break;}
    44             phi[i*pri[j]][0]=phi[i][0]*(pri[j]-1);
    45         }
    46     }
    47     for(L i=1;i<M;i++){
    48         phi[i][2]=(phi[i-1][2]+1LL*i*i%MOD*phi[i][0])%MOD;
    49         phi[i][1]=(phi[i-1][1]+i*phi[i][0])%MOD;
    50         phi[i][0]=(phi[i-1][0]+phi[i][0])%MOD;
    51     }
    52     L cas; cin>>cas;
    53     while(cas--) Main();
    54 }

     

     

  • 相关阅读:
    线程池原理和实现
    线程
    ajax、xstream、json
    上传、下载、javamail
    过滤器
    监听器、国际化
    jsp、javabean、el
    jstl、标签
    jsp、cookie、httpsession
    个人觉得比较好用的chrome插件
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/9878724.html
Copyright © 2011-2022 走看看