List of Intergers

题目大意

求第大的大于等于 且与 互质的数

分析

即,求最小的 使:

莫比乌斯反演

那么看见这个形式,自然而然地会想到这个东西:

所以就可以把 写成:

那么交求和顺序,先枚举 的因子 ,可以得到:

那么,这个时候,后面这一块,已经是十分好求的了,可以直接枚举 范围内 的因子(顺便得到 )的因子,按照这个直接加就可以了

容斥

还是考虑,换一种写法呢就是

那么就是说,不合法的就是

那么按照套路,还是应该用总共的减去不合法的,

那么就要枚举的每个因子对答案的贡献

同样的,还是可以得到容斥系数就是

那么还是能够得到同一个式子:

当然,这并不是巧合,有兴趣的同学可以自行了解一下(我也说不清)

时间复杂度为

Code

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int maxn = 1e7 + 10;
const int mod = 1e9 + 7;

inline int __read()
{
    int x(0), t(1);
    char o (getchar());
    while (o < '0' || o > '9') {
        if (o == '-') t = -1;
        o = getchar();
    }
    for (; o >= '0' && o <= '9'; o = getchar()) {
        x = (x << 1) + (x << 3) + (o ^ 48);
    }
    return x * t;
}

int mu[maxn], pr[maxn], cnt, line;
bool vis[maxn];

inline void Init()
{
    mu[1] = 1;
    for (int i = 2; i < maxn; ++i) {
        if (!vis[i]) pr[++cnt] = i, mu[i] = -1;
        for (int j = 1; j <= cnt && i * pr[j] < maxn; ++j) {
            vis[i * pr[j]] = 1;
            if (i % pr[j]) mu[i * pr[j]] = -mu[i];
            else break;
        }
    }
}

inline int Query(int n, int x)
{
    int ans(0);
    for (int l = 1; l * l <= x; ++l) {
        if (x % l) continue;
        ans += mu[l] * (n / l);
        if (l * l < x) ans += mu[x / l] * (n / (x / l));
    }
    return ans;
}

signed main()
{
    Init();
    int T = __read();
    while (T--) {
        int x = __read(), p = __read(), k = __read();
        int l(1), r(1e7), ans(0);
        line = Query(x, p);
        while (l <= r) {
            int mid = (l + r) >> 1;
            if (Query(mid, p) - line >= k) ans = mid, r = mid - 1;
            else l = mid + 1;
        }
        printf ("%d\n", ans);
    }
    system("pause");
}

UPT:有位机房巨佬认为我写的这个是有点小问题的,我觉得这个可以解释一下

他的意思是按照样例给的,我的函数求得的的答案都是,那么为什么我取得的是而不是,然后并不互质,为什么对还有答案呢?

回到最开头,有这样一个东西:

会发现,我们求得的值,并不是说是第几个,我们求得的值是在有几个

令:

时,当且仅当,所以,我们二分答案要取的是第一个满足条件的数