[Luogu P2522] [BZOJ 2301] [HAOI2011]Problem b

洛谷传送门

BZOJ传送门

题目描述

对于给出的nn个询问,每次求有多少个数对(x,y)(x,y),满足axba≤x≤bcydc≤y≤d,且gcd(x,y)=kgcd(x,y) = kgcd(x,y)gcd(x,y)函数为xxyy的最大公约数。

输入输出格式

输入格式:

第一行一个整数nn,接下来nn行每行五个整数,分别表示aabbccddkk

输出格式:

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

输入输出样例

输入样例#1:

2
2 5 1 5 1
1 5 1 5 2

输出样例#1:

14
3

说明

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

解题分析

我们先推出这个玩意怎么求, 其他的可以通过作差得到(不妨设nmn\le m):
i=1nj=1m[gcd(i,j)=k]=i=1nkj=1mk[gcd(i,j)=1]=i=1nkj=1mkdgcd(i,j)μ(d)=d=1nkμ(d)nkdmkd \sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)=k] \\ =\sum_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{k}\rfloor}[gcd(i,j)=1] \\ =\sum_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{k}\rfloor}\sum_{d|gcd(i,j)}\mu(d) \\ =\sum_{d=1}^{\lfloor\frac{n}{k}\rfloor}\mu(d)\lfloor\frac{\lfloor\frac{n}{k}\rfloor}{d}\rfloor\lfloor\frac{\lfloor\frac{m}{k}\rfloor}{d}\rfloor
然后线筛μ(i)\mu(i), 下底分块即可。

代码如下:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <algorithm>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define ll long long
#define MX 50050
template <class T>
IN void in(T &x)
{
    x = 0; R char c = gc;
    for (; !isdigit(c); c = gc);
    for (;  isdigit(c); c = gc)
    x = (x << 1) + (x << 3) + c - 48;
}
int pcnt;
int miu[MX], pri[MX];
bool npr[MX];
void get_miu()
{
    R int i, j, tar;
    miu[1] = 1;
    for (i = 2; i <= 50000; ++i)
    {
        if (!npr[i]) pri[++pcnt] = i, miu[i] = -1;
        for (j = 1; j <= pcnt; ++j)
        {
            tar = i * pri[j];
            if (tar > 50000) break;
            npr[tar] = true;
            if (!(i % pri[j])) {miu[tar] = 0; break;}
            miu[tar] = -miu[i];
        }
    }
    for (R int i = 1; i <= 50000; ++i) miu[i] += miu[i - 1];
}
IN ll calc(R int up1, R int up2, R int k)
{
    if (up1 > up2) std::swap(up1, up2);
    int bd = up1 / k, bd2 = up2 / k;
    R int lef = 1, rig;
    ll ret = 0;
    W (lef <= bd)
    {
        rig = std::min(bd / (bd / lef), bd2 / (bd2 / lef));
        ret += 1ll *(miu[rig] - miu[lef - 1]) * (bd / lef) * (bd2 / lef);
        lef = rig + 1;
    }
    return ret;
}
int main()
{
    int T, a, b, c, d, k;
    in(T); get_miu();
    W (T--)
    {
        in(a), in(b), in(c), in(d), in(k);
        ll ans = calc(b, d, k) - calc(a - 1, d, k) - calc(b, c - 1, k) + calc(a - 1, c - 1, k);
        printf("%lld\n", ans);
    }
}
发布了458 篇原创文章 · 获赞 88 · 访问量 3万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览