2020牛客多校第七场H-Dividing

https://ac.nowcoder.com/acm/contest/5672/H

题意

正整数二元组 Legend Tuple (n, k) 是这样定义的

  • (1, k) 总是 Legend Tuple

  • 若 (n, k) 是 Legend Tuple, 那么 (n + k, k) 也是

  • 若 (n, k) 是 Legend Tuple, 那么 (nk, k) 也是

统计有多少个 Legend Tuple (n, k) 满足 1 ≤ n ≤ N, 1 ≤ k ≤ K, 其中 N 和 K 是不超过 10^12 的整数

题解

可以很容易发现答案即为n%k==0,或者(n-1)%k==0的对数

对于一部分k,n/k是相等的,所以可以直接整除分块,分别计算情况1和情况2的答案即可

但要注意整除分块的r边界不要超过k,否则会导致答案错误

因为这点wa了好几发

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct READ {
    inline char read() {
    #ifdef _WIN32
        return getchar();
    #endif
        static const int IN_LEN = 1 << 18 | 1;
        static char buf[IN_LEN], *s, *t;
        return (s == t) && (t = (s = buf) + fread(buf, 1, IN_LEN, stdin)), s == t ? -1 : *s++;
    }
    template <typename _Tp> inline READ & operator >> (_Tp&x) {
        static char c11, boo;
        for(c11 = read(),boo = 0; !isdigit(c11); c11 = read()) {
            if(c11 == -1) return *this;
            boo |= c11 == '-';
        }
        for(x = 0; isdigit(c11); c11 = read()) x = x * 10 + (c11 ^ '0');
        boo && (x = -x);
        return *this;
    }
} in;

const int N = 2e5 + 50;
const ll p = 1e9 + 7;
int main() {
    ll n, k;
    in >> n >> k;
    ll ans = 0;
    for (ll l = 1, r; l <= k; l = r + 1) {
        ll x = (n / l);
        if (x == 0) break;
        r = n / x;
        r = min(r, k);
        ans = (ans + ((r - l + 1) % p) * ((n / l) % p) % p) % p;
    }
    for (ll l = 2, r; l <= k; l = r + 1) {
        ll x = (n - 1) / l;
        if (x == 0) {
            ans = (ans + k - l + 1) % p;
            break;
        }
        r = (n - 1) / x;
        r = min(r, k);
        ans = (ans + ((r - l + 1) % p) * (((n - 1) / l + 1) % p) % p) % p;
    }
    printf("%lld
", ans);
    return 0;
}
//1000000000000 1000000000000
原文地址:https://www.cnblogs.com/artoriax/p/13632179.html