• [SDOI2015]约数个数和


    题目大意:
      $q(qleq50000)$组询问,对于给定的$n,m(n,mleq50000)$,求$displaystylesum_{i=1}^nsum_{j=1}^m au(ij)$。

    思路:
      $displaystyle au(ij)=sum_{x|i}sum_{y|j}[gcd(x,y)==1]$。

    $$
    egin{align*}
    原式&=sum_{i=1}^nsum_{j=1}^msum_{x|i}sum_{y|j}[gcd(x,y)==1]\
    &=sum_{i=1}^nsum_{j=1}^msum_{x|i}sum_{y|j}sum_{d|gcd(x,y)}mu(d)\
    &=sum_{i=1}^nsum_{j=1}^msum_{d|gcd(i,j)}mu(d) au(frac id) au(frac jd)\
    &=sum_{d=1}^{min(n,m)}sum_{i=1}^{lfloorfrac nd floor} au(i)sum_{j=1}^{lfloorfrac md floor} au(j)
    end{align*}
    $$
      其中$sum au(i)$可以线性筛预处理,$d$可以数论分块枚举,单次询问复杂度$O(sqrt n)$。

     1 #include<cstdio>
     2 #include<cctype>
     3 #include<algorithm>
     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=50001,M=5134;
    13 bool vis[N];
    14 int p[M],mu[N],tau[N],cnt[N],sum_mu[N],sum_tau[N];
    15 inline void sieve() {
    16     mu[1]=tau[1]=sum_mu[1]=sum_tau[1]=1;
    17     for(register int i=2;i<N;i++) {
    18         if(!vis[i]) {
    19             p[++p[0]]=i;
    20             mu[i]=-1;
    21             cnt[i]=1;
    22             tau[i]=2;
    23         }
    24         for(register int j=1;j<=p[0]&&i*p[j]<N;j++) {
    25             vis[i*p[j]]=true;
    26             if(i%p[j]==0) {
    27                 mu[i*p[j]]=0;
    28                 cnt[i*p[j]]=cnt[i]+1;
    29                 tau[i*p[j]]=tau[i]/cnt[i*p[j]]*(cnt[i*p[j]]+1);
    30                 break;
    31             }
    32             mu[i*p[j]]=-mu[i];
    33             cnt[i*p[j]]=1;
    34             tau[i*p[j]]=tau[i]*2;
    35         }
    36         sum_mu[i]=sum_mu[i-1]+mu[i];
    37         sum_tau[i]=sum_tau[i-1]+tau[i];
    38     }
    39 }
    40 int main() {
    41     sieve();
    42     for(register int T=getint();T;T--) {
    43         const int n=getint(),m=getint(),lim=std::min(n,m);
    44         int64 ans=0;
    45         for(register int l=1,r;l<=lim;l=r+1) {
    46             r=std::min(n/(n/l),m/(m/l));
    47             ans+=(int64)(sum_mu[r]-sum_mu[l-1])*sum_tau[n/l]*sum_tau[m/l];
    48         }
    49         printf("%lld
    ",ans);
    50     }
    51     return 0;
    52 }
  • 相关阅读:
    ACM-ICPC SouthWestern Europe Regional Contest 2017题解
    Ubuntu系统Anaconda下载安装与切换源教程
    HZNUOJ开发者学习计划
    Codeforces Round #473 (Div. 2)
    正方教务系统自动评教代码
    QQ空间自动点赞
    妈妈我要当全栈工程师
    基于Koa开发学生导师管理系统
    SSH框架实现登陆界面
    谈ACM生涯总结的经验
  • 原文地址:https://www.cnblogs.com/skylee03/p/8477009.html
Copyright © 2020-2023  润新知