zoukankan      html  css  js  c++  java
  • SPOJ:[DIVCNT3]Counting Divisors

     

    题目大意:求1~N的每个数因子数的立方和。

    题解:由于N过大,我们不能直接通过线性筛求解。我们可以采用洲阁筛。

    洲阁筛的式子可以写成:

    对于F(1~√n),可以直接线性筛求解。

    对于,我们进行以下DP:

    g[i][j]为1~j中,与前i个质数互质的数的F值之和。

    dp过程中,有

    如果p[i]>j,则g[i][j]=F(1);

    如果p[i]*p[i]>j>=p[i],则g[i][j]=g[i-1][j]-p[i]^k*F(1)=g[d][j]-(p[d+1]^k~p[i]^k)*F(1),其中p[d]为最大的p[d]*p[d]<=j的质数;

    如果j>=p[i]*p[i],我们老老实实调用式子。

    对于,我们用类似的方式DP:

    f[i][j]为1~j中,只以第i个到第m个质数为质因子的数的F值之和(m为√N以内质数个数)。

    类似的,dp过程中,有

    如果p[i]>j,则f[i][j]=F(1);

    如果p[i]*p[i]>j>=p[i],则f[i][j]=f[i+1][j]+F(p[i])*F(1)=F(1)+F(p[i]~p[e])*F(1),其中p[e]为最大的p[e]<=j的质数;

    如果j>=p[i]*p[i],我们老老实实调用式子。

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 long long block,n,lb[2000005],dp[2000005],zs[2000005],ans[2000005],ans2;
     4 bool bo[2000005],bo2[2000005];
     5 int dp2[2000005],dp3[2000005],m,mm,tot,j,bo3[2000005],tt;
     6 void xxs(int n)
     7 {
     8     ans[1]=1;
     9     for(int i=2;i<=n;i++)
    10     {
    11         if(bo[i]==0){ mm++; zs[mm]=i; ans[i]=4; bo2[i]=1; bo3[i]=4; }
    12         for(int j=1;j<=mm;j++)
    13         if(zs[j]*i>n)break;else
    14         if(i%zs[j]==0)
    15         {
    16             if(bo2[i]==1)bo2[i*zs[j]]=1; bo3[i*zs[j]]=bo3[i]+3; ans[i*zs[j]]=ans[i]/bo3[i]*(bo3[i]+3);
    17             bo[i*zs[j]]=1; break;
    18         }else { ans[i*zs[j]]=ans[i]*4; bo[i*zs[j]]=1; bo3[i*zs[j]]=4; }
    19     }
    20 }
    21 int dy(long long x){ if(x<=block)return x;else return tot-n/x+1; }
    22 long long get(int i,int j)
    23 {
    24     if(dp2[j]==i)return dp[j];else 
    25     if(lb[j]<zs[i]){ if(j>0)return 1; return 0; } 
    26     return dp[j]-i+dp2[j];
    27 }
    28 long long get2(int i,int j)
    29 {
    30     if(dp2[j]==i)return dp[j];else 
    31     if(lb[j]<zs[i])return 1; 
    32     return (dp3[j]-i+1)*4+1;
    33 }
    34 int main()
    35 {
    36     scanf("%d",&tt); xxs(500000);
    37     for(int ii=1;ii<=tt;ii++)
    38     {
    39         scanf("%lld",&n); block=(int)sqrt(n); ans2=0;
    40         for(m=1;m<=mm;m++)if(zs[m]>block)break; m--; tot=0;
    41         for(int i=1;i<=block;i++){ lb[++tot]=i; if(1ll*i*i<n)lb[++tot]=n/i; }
    42         sort(lb+1,lb+tot+1);
    43         for(int i=1;i<=tot;i++)dp[i]=lb[i],dp2[i]=0;
    44         for(int i=1;i<=m;i++)
    45         {
    46             for(int j=tot;j>=1;j--)
    47             {
    48                 if(lb[j]<zs[i]*zs[i])break; dp2[j]=i;
    49                 dp[j]=dp[j]-get(i-1,dy(lb[j]/zs[i]));
    50             }
    51         }
    52         for(int i=1;i<=block;i++)
    53         ans2=ans2+ans[i]*(get(m,tot-i+1)-1)*4;
    54         j=1; 
    55         for(int i=1;i<=tot;i++)
    56         {
    57             dp[i]=1; dp2[i]=m+1;
    58             while((j<=m)and(zs[j]<=lb[i]))j++; dp3[i]=j-1;
    59         }
    60         for(int i=m;i>=1;i--)
    61         {
    62             for(int j=tot;j>=1;j--)
    63             {
    64                 if(lb[j]<zs[i]*zs[i])break; dp[j]=get2(i+1,j); dp2[j]=i;
    65                 long long t=j,l=1; 
    66                 while(lb[t]>=zs[i])
    67                 {
    68                     t=dy(lb[t]/zs[i]); l+=3;
    69                     dp[j]=dp[j]+l*get2(i+1,t);
    70                 }
    71             }
    72         }
    73         ans2=ans2+get2(1,tot);
    74         printf("%lld
    ",ans2);
    75     }
    76 } 
    View Code
  • 相关阅读:
    js实现两种实用的排序算法——冒泡、快速排序
    node端代理浏览器路由 解决浏览器跨域问题
    HTTP Request header
    移动H5前端性能优化指南
    express下使用ES6
    Nginx Location配置总结
    NODE_ENV=production 环境变量设置
    css3逐帧动画
    js scheme 打开手机app的方法
    jQuery hashchange监听浏览器url变化
  • 原文地址:https://www.cnblogs.com/GhostReach/p/8298375.html
Copyright © 2011-2022 走看看