2019 ICPC 南京站網絡賽 K Sum

自閉一下午……
思路

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <unordered_map>
using namespace std;

typedef long long ll;

const ll mod = 1e9+7;
const int maxn = 6e6+5;

unordered_map<int, ll> sm;

int cnt;
int pri[maxn];
bool is[maxn];
ll f[maxn];
ll sf[maxn];

void init () {
    f[1] = is[0] = is[1] = 1;
    for (int i = 2; i < maxn; ++i) {
        if (!is[i]) {
            pri[++cnt] = i;
            f[i] = (1ll*i*i%mod-1+mod)%mod;
        }
        for (int j = 1; j <= cnt && 1ll*i*pri[j] < maxn; ++j) {
            is[i*pri[j]] = 1;
            if (i % pri[j] == 0) {
                f[i*pri[j]] = 1ll*f[i]*pri[j]%mod*pri[j]%mod;
                break;
            }
            else {
                f[i*pri[j]] = 1ll*f[i]*f[pri[j]]%mod;
            }
        }
    }
    for (int i = 1; i < maxn; ++i) {
        sf[i] = sf[i-1]+f[i];
        sf[i] %= mod;
    }
}

ll qm (ll a, ll b) {
    ll res = 1;
    a %= mod;
    while (b) {
        if (b&1) {
            res = res*a%mod;
        }
        a = a*a%mod;
        b >>= 1;
    }
    return res;
}

ll inv (ll k) {
    return qm(k, mod-2);
}

ll get_sum1 (ll k) {
    return k*(k+1)%mod*(2*k%mod+1)%mod*inv(6)%mod;
}

ll get_sum2 (ll n, ll k, ll tk) {
    if (n == 1) {
        return (tk-1+mod)%mod;
    }
    else {
        return n*n%mod*(qm(n, k-1)+mod-1)%mod*inv(n-1)%mod;
    }
}

ll get_sf (ll n) {
    if (n < maxn) {
        return sf[n];
    }
    if (sm[n]) {
        return sm[n];
    }
    ll res = get_sum1(n);
    for (ll l = 2, r; l <= n; l = r+1) {
        r = n/(n/l);
        res -= get_sf(n/l)*(r-l+1)%mod;
        res = (res%mod+mod)%mod;
    }
    sm[n] = res;
    return res;
}

char str[maxn];

int main(){
    init();
    int t;
    scanf("%d", &t);
    for (int _ = 1; _ <= t; ++_) {
        ll n;
        scanf("%lld", &n);
        ll k = 0, tk = 0, res = 0;
        scanf("%s", str);
        int len = strlen(str);
        for (int i = 0; i < len; ++i) {
            tk = tk*10+str[i]-'0';
            tk %= mod;
            k = k*10+str[i]-'0';
            k %= mod-1;
        }
        for (ll l = 1, r; l <= n; l = r+1) {
            r = n/(n/l);
            res += get_sum2(n/l, k, tk)*(get_sf(r)-get_sf(l-1)+mod)%mod;
            res %= mod;
        }
        cout << res << '\n';
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章