zoukankan      html  css  js  c++  java
  • bzoj 2301 莫比乌斯反演

     对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数。

    这里题目意思很明显

    对于要求的f[n] = sigma (a≤x≤b) sigma(c≤y≤d) [gcd(x,y)=k] =  sigma (1≤x≤b) sigma(1≤y≤d) [gcd(x,y)=k] + sigma (1≤x≤a-1) sigma(1≤y≤c-1) [gcd(x,y)=k] - sigma (1≤x≤a-1) sigma(1≤y≤d) [gcd(x,y)=k] -  sigma (1≤x≤b) sigma(1≤y≤c-1) [gcd(x,y)=k] 

    对于每一个g[n] = sigma(1≤x≤a) sigma(1≤y≤c) [gcd(x,y)=k] = sigma(1≤x≤a/k) sigma(1≤y≤c/k) [gcd(x,y)=1] = sigma(1≤x≤a/k) sigma(1≤y≤c/k) sigma(d|gcd(x,y)) mu[d] = sigma(d) mu[d]*a/k/d*c/k/d

    a/k/d*c/k/d 这一段区间相等的部分可以加在一起算,得到当前一样值的结束是 min(x/(x/i) , y/(y/i)) 

    记录莫比乌斯函数的前缀和就可以整段区间更新,这样循环就缩小到了sqrt(n)的复杂度

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 #define N 50000
     5 int mu[N+10] , prime[N+10] , tot , sum[N+10];
     6 bool check[N+10];
     7 
     8 void get_mu()
     9 {
    10     mu[1] = 1;
    11     for(int i=2 ; i<=N ; i++){
    12         if(!check[i]){
    13             prime[tot++] = i;
    14             mu[i] = -1;
    15         }
    16         for(int j=0 ; j<tot ; j++){
    17             if((ll)i*prime[j]>N) break;
    18             check[i*prime[j]] = true;
    19             if(i%prime[j]){
    20                 mu[i*prime[j]] = -mu[i];
    21             }else break;
    22         }
    23     }
    24     for(int i=1 ; i<=N ; i++) sum[i]=sum[i-1]+mu[i];
    25 }
    26 
    27 int a,b,c,d,k;
    28 
    29 int solve(int x , int y)
    30 {
    31     x/=k , y/=k;
    32     int mx = min(x , y) , len , ret=0;
    33     for(int i=1 ; i<=mx ; i=len+1)
    34     {
    35        // cout<<i<<" "<<ret<<endl;
    36         len = min(x/(x/i) , y/(y/i));
    37         ret += x/i*(y/i)*(sum[len]-sum[i-1]);
    38     }
    39     return ret;
    40 }
    41 
    42 int main()
    43 {
    44     //freopen("in.txt" , "r" , stdin);
    45     get_mu();
    46     int T;
    47     scanf("%d" , &T);
    48     while(T--){
    49         scanf("%d%d%d%d%d" , &a , &b , &c , &d , &k);
    50         printf("%d
    " , solve(b,d)+solve(a-1,c-1)-solve(a-1,d)-solve(b,c-1));
    51     }
    52     return 0;
    53 }
  • 相关阅读:
    Redis系列--3.redis配置
    Redis系列--2.redis安装
    Redis系列--1.redis概述
    Redis系列--4.常用命令汇总
    Redis系列之(六)——集群redis cluster
    Redis系列之(五)——哨兵
    Redis系列之(四)——深入reids优化
    Redis系列之(三)——持久化与复制
    Redis系列之(一)——开发基础
    Python执行系统命令的方法
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4784338.html
Copyright © 2011-2022 走看看