• [HAOI 2011]Problem b


    Description

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

    Input

    第一行一个整数n,接下来n行每行五个整数,分别表示a、b、c、d、k

    Output

    共n行,每行一个整数表示满足要求的数对(x,y)的个数

    Sample Input

    2
    2 5 1 5 1
    1 5 1 5 2

    Sample Output

    14
    3

    HINT

    100%的数据满足:1≤n≤50000,1≤a≤b≤50000,1≤c≤d≤50000,1≤k≤50000

    题解

    记 $f(x, y)$ 为满足 $gcd(i,j)=k$ 的数对 $(i,j)~~(iin[1,x],jin[1,y])$ 的个数。

    由容斥原理,答案就是 $ans=f(b,d)-f((a-1),d)-f(b,(c-1))+f((a-1),(c-1))$ 。

    我们现在考虑如何求 $f(x,y)$ 。

    我们按照以往的套路,将 $k$ 提出,显然 $$f(a,b)=sum_{i=1}^{leftlfloorfrac{a}{k} ight floor}sum_{j=1}^{leftlfloorfrac{b}{k} ight floor}[gcd(i,j)=1]$$

    由公式 $sum_{dmid n} mu(d)=[n=1]$ ,我们得到

    $$Rightarrow sum_{i=1}^{leftlfloorfrac{a}{k} ight floor}sum_{j=1}^{leftlfloorfrac{b}{k} ight floor}sum_{dmid gcd(i,j)}mu(d)$$

    我们将 $mu$ 提前

    egin{aligned} &Rightarrowsum_{d=1}^{minleft{leftlfloorfrac{a}{k} ight floor,leftlfloorfrac{b}{k} ight floor ight}}mu(d)sum_{i=1,dmid i}^{leftlfloorfrac{a}{k} ight floor}sum_{j=1,dmid j}^{leftlfloorfrac{b}{k} ight floor}1\&Rightarrowsum_{d=1}^{minleft{leftlfloorfrac{a}{k} ight floor,leftlfloorfrac{b}{k} ight floor ight}}mu(d)cdotleftlfloorfrac{leftlfloorfrac{a}{k} ight floor}{d} ight floorcdotleftlfloorfrac{leftlfloorfrac{b}{k} ight floor}{d} ight floorend{aligned}

    得到这个式子还有第二个方Fa♂,这里也提一下。

    令 $F(d)$ 为 $dmid gcd(i,j)$ 的数对 $(i,j)$ 个数, $f(d)$ 为 $d=gcd(i,j)$ 的数对 $(i,j)$ 个数。

    由题 $$F(k)=sum_{d=1}^{minleft{leftlfloorfrac{a}{k} ight floor,leftlfloorfrac{b}{k} ight floor ight}}f(kd)$$

    由莫比乌斯反演定理 $F(n)=sum_{nmid d} f(d)Rightarrow f(n)=sum_{nmid d} mu(frac{d}{n})F(d)$

    egin{aligned}Rightarrow f(k)&=sum_{d=1}^{minleft{leftlfloorfrac{a}{k} ight floor,leftlfloorfrac{b}{k} ight floor ight}}mu(d)F(kd)\&=sum_{d=1}^{minleft{leftlfloorfrac{a}{k} ight floor,leftlfloorfrac{b}{k} ight floor ight}}mu(d)cdotleftlfloorfrac{a}{kd} ight floorcdotleftlfloorfrac{b}{kd} ight floorend{aligned}

    那么我们现在只需要 $O(n)$ 的枚举 $d$ 就可以了,但对于多组询问,这个复杂度还是吃不消的。

    我们考虑在计算的时候 $leftlfloorfrac{leftlfloorfrac{n}{k} ight floor}{d} ight floor$ 是一个分段的,有较长的一段区间内的数是相等的。可以证明这段区间的长度是 $sqrt{n}$ 的。

    证明:

      1.当 $1leq d < sqrt n$ 时, $d$ 就只有 $sqrt n$ 个, $leftlfloor{n over d} ight floor$ 最多有 $sqrt n$ 个。

      2.当 $sqrt n leq d leq n$ 时,由于 $leftlfloor{n over d} ight floor$ 小于 $sqrt n$ ,所以 $leftlfloor{n over d} ight floor$ 最多有 $sqrt n$ 个。

    证毕。

    显然对于一段区间内 $leftlfloorfrac{leftlfloorfrac{a}{k} ight floor}{d} ight floor$ 和 $leftlfloorfrac{leftlfloorfrac{b}{k} ight floor}{d} ight floor$ 相同的数我们可以直接处理 $mu$ 的前缀,直接求即可。而相同值的区间的右端点为 $leftlfloor frac{n}{leftlfloorfrac{n}{d} ight floor} ight floor$ 。

    证明:

    对于 $n$ 来说,找到最大的 $j$ 满足 $$leftlfloorfrac{n}{i} ight floor leqleftlfloorfrac{n}{j} ight floor$$

    化简一下得到 $$jleq leftlfloorfrac{n}{leftlfloorfrac{n}{i} ight floor} ight floor$$

    那么在计算时在分别关于 $a, b$ 的表达式中取一个较小值即可。时间复杂度 $O(nsqrt n)$ 。

     1 //It is made by Awson on 2018.1.19
     2 #include <set>
     3 #include <map>
     4 #include <cmath>
     5 #include <ctime>
     6 #include <queue>
     7 #include <stack>
     8 #include <cstdio>
     9 #include <string>
    10 #include <vector>
    11 #include <cstdlib>
    12 #include <cstring>
    13 #include <iostream>
    14 #include <algorithm>
    15 #define LL long long
    16 #define Abs(a) ((a) < 0 ? (-(a)) : (a))
    17 #define Max(a, b) ((a) > (b) ? (a) : (b))
    18 #define Min(a, b) ((a) < (b) ? (a) : (b))
    19 #define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
    20 #define writeln(x) (write(x), putchar('
    '))
    21 using namespace std;
    22 const int N = 50000;
    23 const int INF = ~0u>>1;
    24 void read(int &x) {
    25     char ch; bool flag = 0;
    26     for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
    27     for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
    28     x *= 1-2*flag;
    29 }
    30 void write(LL x) {
    31     if (x > 9) write(x/10);
    32     putchar(x%10+48);
    33 }
    34 
    35 LL mu[N+5]; int a, b, c, d, k;
    36 void get_mu() {
    37     int isprime[N+5], prime[N+5], tot = 0;
    38     memset(isprime, 1, sizeof(isprime)); isprime[1] = 0, mu[1] = 1;
    39     for (int i = 2; i <= N; i++) {
    40     if (isprime[i]) mu[i] = -1, prime[++tot] = i;
    41     for (int j = 1; j <= tot && i*prime[j] <= N; j++)
    42         if (!(i%prime[j])) {isprime[i*prime[j]] = 0, mu[i*prime[j]] = 0; break; }
    43         else isprime[i*prime[j]] = 0, mu[i*prime[j]] = -mu[i];
    44     mu[i] += mu[i-1];
    45     }
    46 }
    47 LL cal(int x, int y) {
    48     if (x > y) Swap(x, y); LL ans = 0;
    49     for (int i = 1, last; i <= x; i = last+1) {
    50     last = Min(x/(x/i), y/(y/i));
    51     ans += (LL)(mu[last]-mu[i-1])*(x/i)*(y/i);
    52     }
    53     return ans;
    54 }
    55 void work() {
    56     read(a), read(b), read(c), read(d), read(k);
    57     writeln(cal(b/k, d/k)-cal(b/k, (c-1)/k)-cal((a-1)/k, d/k)+cal((a-1)/k, (c-1)/k));
    58 }
    59 int main() {
    60     int t; read(t); get_mu();
    61     while (t--) work();
    62     return 0;
    63 }
  • 相关阅读:
    利用.net Core 对程序集中的类 进行统一依赖注入
    接口中定义异步的方法
    在efcore 中创建类 通过实现IEntityTypeConfiguration<T>接口 实现实体类的伙伴类 实现FluentApi
    在vs2017 版本15.7.6中不支持2.1.0以上版本的net core sdk
    在.net core不同的版本中 webabi引用的包不同
    SQL语句中使用Group by
    DDD实战12 值对象不创建表,而是直接作为实体中的字段
    src与href的区别。
    cookies,sessionStorage 和 localStorage 的区别
    javascript阻止事件冒泡和浏览器的默认行为
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/8318709.html
Copyright © 2020-2023  润新知