• 【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 }
  • 相关阅读:
    C++ Sqlite3的基本使用
    DirectX11 初探XMVECOTR&XMMATRIX
    lib和dll文件的初了解
    游戏设计模式——C++单例类
    C++11智能指针的深度理解
    你的文章里为什么不放源码Github链接了
    堡垒机的核心武器:WebSSH录像实现
    Asciinema文章勘误及Web端使用介绍
    Asciinema:你的所有操作都将被录制
    Django实现WebSSH操作物理机或虚拟机
  • 原文地址:https://www.cnblogs.com/gzez181027/p/bzoj2820.html
Copyright © 2020-2023  润新知