zoukankan      html  css  js  c++  java
  • 【bzoj2820】GCD

    Description

    给定n,m(n,m<=107), 求 $\sum\limits_{x=1}^{n}\sum\limits_{y=1}^{m}[gcd(x,y)=质数]$。(多组数据,T<=10000)


    Solution

    这题是一道模板题,用下面这条公式就能解决啦~

    $\sum\limits_{d|n}μ(d)=[n=1]$

    $ans=\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}[gcd(i,j)=质数]$

    $=\sum\limits_{p}\sum\limits_{i=1}^{\left\lfloor\frac{n}{p}\right\rfloor}\sum\limits_{j=1}^{\left\lfloor\frac{m}{p}\right\rfloor}[gcd(i,j)=1]$ (p为质数)

    $=\sum\limits_{p}\sum\limits_{i=1}^{\left\lfloor\frac{n}{p}\right\rfloor}\sum\limits_{j=1}^{\left\lfloor\frac{m}{p}\right\rfloor}\sum\limits_{d|i,d|j}μ(d)$

    $=\sum\limits_{p}\sum\limits_{d=1}^{\left\lfloor\frac{n}{p}\right\rfloor}μ(d)\left\lfloor\frac{n}{pd}\right\rfloor\left\lfloor\frac{m}{pd}\right\rfloor$

    记 $c=pd$ ,则

    $ans=\sum\limits_{c=1}^{n}\sum\limits_{p|c}μ(\frac{c}{p})\left\lfloor\frac{n}{c}\right\rfloor\left\lfloor\frac{m}{c}\right\rfloor$

    最后用线性筛预处理出$μ(d)$的前缀和,然后按照$\left\lfloor\frac{n}{c}\right\rfloor$的值分块处理就可以啦,时间复杂度$O(T\sqrt{n})$。

    Code

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int N=10000000;
     6 int t,n,m,p[N+10]={0},miu[N+10]={0,1},g[N+10]={0},f[N+10]={0};
     7 bool check[N+10]={false};
     8 void get_miu(){
     9     for(int i=2;i<=N;i++){
    10         if(!check[i]){
    11             miu[p[++p[0]]=i]=-1;
    12             g[i]=1;
    13         }
    14         for(int j=1;i*p[j]<=N&&j<=p[0];j++){
    15             check[i*p[j]]=true;
    16             if(i%p[j]){
    17                 miu[i*p[j]]=-miu[i];
    18                 g[i*p[j]]=miu[i]-g[i];
    19             }
    20             else{
    21                 g[i*p[j]]=miu[i];
    22                 break;
    23             }
    24         }
    25     }
    26     for(int i=1;i<=N;i++)
    27         f[i]=f[i-1]+g[i];
    28     return;
    29 }
    30 int main(){
    31     get_miu();
    32     scanf("%d",&t);
    33     while(t--){
    34         scanf("%d%d",&n,&m);
    35         if(n>m)
    36             swap(n,m);
    37         long long ans=0;
    38         for(int i=1,j;i<=n;i=j+1)
    39             ans+=(long long)(f[j=min(n/(n/i),m/(m/i))]-f[i-1])*(n/i)*(m/i);
    40         printf("%lld\n",ans);
    41     }
    42     return 0;
    43 }
  • 相关阅读:
    怎么做接口测试,概念及常用方法一
    Maven 常用命令
    终端/Shell 快捷键
    Linux/Unix split 大文件分割合并
    macOS 跳过非 AppStore 下载的软件打开时的验证步骤
    docker[-compose] 连接内网其他容器地址
    iOS现有工程 集成 Cordova/Ionic
    Retrofit2 上传图片等文件
    ButterKnife 绑定 RadioGroup
    使用 Sublime Text 3 开发 React
  • 原文地址:https://www.cnblogs.com/gzez181027/p/bzoj2820.html
Copyright © 2011-2022 走看看