• [CF665F]Four Divisors


    题目大意:
      给定$n(nleq10^{11})$,求$displaystylesum_{i=1}^n[ au(i)=4]$。

    思路:
      设$p,q$为不相等的质数,则满足$ au(i)=4$的数$i$一定可以表示成$pq$或$p^3$。
      对于$i=pq$的情况,可以先线性筛预处理出$sqrt n$以内的质数,然后用LOJ6235的方法,用洲阁筛求出DP数组$f$。加上$last[j]-1$就是当$p_i^2>j$时不用$-1$转移,也就是加上了$p_i^2>j$的质数个数。此时$f[cnt+1-p_i]$表示的就是$pi(n/p_i)-pi(sqrt n)$。统计答案时,枚举素数$p_i$,求$sum_{p_ileqsqrt n}(pi(n/p_i)-pi(p_i))$即可。
      对于$i=p^3$的情况,直接在筛出来的质数中二分答案即可。
      时间复杂度$Oleft(frac{n^{frac34}}{ln n} ight)$。

    细节:
      $n=1$时二分会挂掉,需要特判。

     1 #include<cmath>
     2 #include<cstdio>
     3 #include<cctype>
     4 #include<algorithm>
     5 #include<functional>
     6 typedef long long int64;
     7 inline int64 getint() {
     8     register char ch;
     9     while(!isdigit(ch=getchar()));
    10     register int64 x=ch^'0';
    11     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    12     return x;
    13 }
    14 const int LIM=316228,P=27294;
    15 bool vis[LIM];
    16 int lim,p[P],sum[LIM],last[LIM*2],cnt;
    17 int64 n,val[LIM*2],f[LIM*2];
    18 inline void sieve() {
    19     for(register int i=2;i<=lim;i++) {
    20         if(!vis[i]) p[++p[0]]=i;
    21         sum[i]=sum[i-1]+!vis[i];
    22         for(register int j=1;j<=p[0]&&i*p[j]<=lim;j++) {
    23             vis[i*p[j]]=true;
    24             if(i%p[j]==0) break;
    25         }
    26     }
    27 }
    28 int main() {
    29     lim=sqrt(n=getint());
    30     sieve();
    31     for(register int64 i=1;i<=n;i=n/(n/i)+1) {
    32         val[++cnt]=n/i;
    33     }
    34     std::reverse(&val[1],&val[cnt]+1);
    35     std::copy(&val[1],&val[cnt+1],&f[1]);
    36     for(register int i=1;i<=p[0];i++) {
    37         for(register int j=cnt;j;j--) {
    38             const int64 k=val[j]/p[i],pos=k<=lim?k:cnt+1-n/k;
    39             if(k<p[i]) break;
    40             f[j]-=f[pos]+last[pos]-i+1;
    41             last[j]=i;
    42         }
    43     }
    44     int64 ans=0;
    45     for(register int i=1;i<=cnt;i++) {
    46         f[i]+=last[i]-1;
    47     }
    48     for(register int i=1;i<=p[0];i++) {
    49         ans+=f[cnt+1-p[i]]-i;
    50     }
    51     if(n!=1) ans+=std::upper_bound(&p[1],&p[p[0]]+1,floor(pow(n,1./3)))-&p[1];
    52     printf("%lld
    ",ans);
    53     return 0;
    54 }
  • 相关阅读:
    WPF中更改键盘默认指令小结
    WPF自己喜欢用的数据验证方式
    重写Windows基类,自定义WPF窗口,实现改回车键为TAB
    用CSS控制表格的框格线
    获取当前鼠标的坐标
    SQL 中的转义字符
    資料站點
    jquery 弹出浮层(div) + 遮蔽层
    Jquery放大镜插件[JMagazine]使用参数简介
    邏輯題 交通事故篇
  • 原文地址:https://www.cnblogs.com/skylee03/p/8485187.html
Copyright © 2020-2023  润新知