zoukankan      html  css  js  c++  java
  • [BZOJ3944]Sum

    题目大意:
      对于给定的$n(n<2^{31})$,求$sum_{i=1}^nvarphi(i)$和$sum_{i=1}^nmu(i)$。

    思路:
      $sum_{i=1}^nvarphi(i)$同BZOJ4805。
      设$S(n)=sum_{i=1}^nmu(i)$。
      因为$sum_{d|n}mu(d)=[n=1]$,$S(n)=sum_{i=1}^n([i=1]-sum_{d|i,d<i}mu(d))=1-sum_{i=2}^nS(lfloorfrac ni floor)$。
      线性筛预处理$S$的前$n^{frac23}$项,剩下的数论分块计算,用哈希表保存已经算过的值,记忆化搜索即可。时间复杂度$O(n^{frac23})$。

    细节:
      两个询问必须写在一个函数里,否则会TLE。

     1 #include<cstdio>
     2 #include<cctype>
     3 #include<hash_map>
     4 typedef long long int64;
     5 inline int getint() {
     6     register char ch;
     7     while(!isdigit(ch=getchar()));
     8     register int x=ch^'0';
     9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    10     return x;
    11 }
    12 const int N=1664511,M=125640;
    13 bool vis[N];
    14 int m,mu[N],phi[N],p[M];
    15 int64 s_mu[N],s_phi[N];
    16 __gnu_cxx::hash_map<int,std::pair<int64,int64> > map;
    17 inline void sieve() {
    18     phi[1]=mu[1]=s_phi[1]=s_mu[1]=1;
    19     for(register int i=2;i<N;i++) {
    20         if(!vis[i]) {
    21             p[++p[0]]=i;
    22             mu[i]=-1;
    23             phi[i]=i-1;
    24         }
    25         for(register int j=1;j<=p[0]&&i*p[j]<N;j++) {
    26             vis[i*p[j]]=true;
    27             if(i%p[j]==0) {
    28                 mu[i*p[j]]=0;
    29                 phi[i*p[j]]=phi[i]*p[j];
    30                 break;
    31             }
    32             mu[i*p[j]]=-mu[i];
    33             phi[i*p[j]]=phi[i]*phi[p[j]];
    34         }
    35         s_mu[i]=s_mu[i-1]+mu[i];
    36         s_phi[i]=s_phi[i-1]+phi[i];
    37     }
    38 }
    39 inline std::pair<int64,int64> calc(const int64 &n) {
    40     if(n<N) return std::make_pair(s_phi[n],s_mu[n]);
    41     if(map.count(n)) return map[n];
    42     std::pair<int64,int64> ans=std::make_pair((int64)n*(n+1)/2,1);
    43     for(register int64 l=2,r;l<=n;l=r+1) {
    44         r=n/(n/l);
    45         std::pair<int64,int64> tmp=calc(n/l);
    46         ans.first-=tmp.first*(r-l+1);
    47         ans.second-=tmp.second*(r-l+1);
    48     }
    49     return map[n]=ans;
    50 }
    51 int main() {
    52     sieve();
    53     for(register int T=getint();T;T--) {
    54         std::pair<int64,int64> ans=calc(getint());
    55         printf("%lld %lld
    ",ans.first,ans.second);
    56     }
    57     return 0;
    58 }
  • 相关阅读:
    CF1539 VP 记录
    CF1529 VP 记录
    CF875C National Property 题解
    CF1545 比赛记录
    CF 1550 比赛记录
    CF1539E Game with Cards 题解
    CF1202F You Are Given Some Letters... 题解
    vmware Linux虚拟机挂载共享文件夹
    利用SOLR搭建企业搜索平台 之九(solr的查询语法)
    利用SOLR搭建企业搜索平台 之四(MultiCore)
  • 原文地址:https://www.cnblogs.com/skylee03/p/8473898.html
Copyright © 2011-2022 走看看