• 数学(数论)BZOJ 3309:DZY Loves Math


    Description

    对于正整数n,定义f(n)为n所含质因子的最大幂指数。例如f(1960)=f(2^3 * 5^1 * 7^2)=3, f(10007)=1, f(1)=0。
    给定正整数a,b,求sigma(sigma(f(gcd(i,j)))) (i=1..a, j=1..b)。

    Input

    第一行一个数T,表示询问数。
    接下来T行,每行两个数a,b,表示一个询问。

    Output

    对于每一个询问,输出一行一个非负整数作为回答。

    Sample Input

    4
    10000
    7558588 9653114
    6514903 4451211
    7425644 1189442
    6335198 4957

    Sample Output

    35793453939901
    14225956593420
    4332838845846
    15400094813

    HINT

    【数据规模】

    T<=10000

    1<=a,b<=10^7

      莫比乌斯反演得到:

    (盗图)

      然后有类似于yy的GCD的做法,分块加速,复杂度变O(√n)

      问题就是如何快速预处理出后面的式子,设其为g(x),这时研究g函数性质,g(x)的取值有哪些规律呢?

      将x分解质因数,x=p1a1*p2a2*p3a3*……*pnan,函数即是将x分解成两个集合,求值再求和。

      1.假设a不全是同一个值,那么那个较小的素数,可以对每个情况属于两个集合使得其值互为相反数,所以值为0。

      2.a值全相等时,易得g(x)=(-1)a-1,根据欧拉线性筛的性质,每个数被最小的素因子枚举到,可以维护两个值,当前的a值,去掉当前最小的素因子后的数。

      然后就可以

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 using namespace std;
     5 const int N=10000010;
     6 int g[N],nxt[N],mem[N];
     7 int prime[N],cnt;
     8 bool check[N];
     9 
    10 void Prepare(){
    11     for(int i=2;i<N;i++){
    12     if(!check[i]){
    13         prime[++cnt]=i;
    14         g[i]=nxt[i]=mem[i]=1;
    15     }
    16     for(int j=1;j<=cnt;j++){
    17         if(i*prime[j]>=N)break;
    18         check[i*prime[j]]=true;
    19         if(i%prime[j]==0){
    20         nxt[i*prime[j]]=nxt[i];
    21         mem[i*prime[j]]=mem[i]+1;
    22         if(nxt[i]==1)g[i*prime[j]]=1;
    23         else if(mem[nxt[i]]==mem[i]+1)
    24             g[i*prime[j]]=-g[nxt[i]];
    25         else g[i*prime[j]]=0;
    26         break;
    27         }
    28         else{
    29         nxt[i*prime[j]]=i;
    30         mem[i*prime[j]]=1;
    31         g[i*prime[j]]=(mem[i]==1)?-g[i]:0;
    32         }
    33     }
    34     }
    35     for(int i=1;i<N;i++)
    36     g[i]+=g[i-1];
    37 }
    38 int T,a,b;
    39 long long ans;
    40 int main(){
    41     Prepare();
    42     scanf("%d",&T);
    43     while(T--){
    44     scanf("%d%d",&a,&b);
    45     if(a>b)swap(a,b);ans=0;
    46     for(int i=1,p=1;i<=a;i=p+1){
    47         p=min(a/(a/i),b/(b/i));
    48         ans+=1ll*(g[p]-g[i-1])*(a/i)*(b/i);
    49     }
    50     printf("%lld
    ",ans);
    51     }
    52     return 0;
    53 }

    维护了。

      

  • 相关阅读:
    查看kafka版本号
    This service allows sftp connections only. 解法
    raid5和raid10的异同
    mpstat命令
    力扣 2020.06.27
    力扣 2020.06.22
    windows10 LTSC 2019 激活
    shell 不等式的表示方法
    C#后台判断一个网站的有效性代码
    C#去除DataTable中的重复数值
  • 原文地址:https://www.cnblogs.com/TenderRun/p/6031544.html
Copyright © 2020-2023  润新知