• 牛客多校6G


    题目链接

    Hasse Diagram

    题解

    一开始推的是(f(x)=sumlimits_{d|x}{g(d)}),其中(g(x))代表本质不同的质因数的个数,后来发现这个函数没有积性,无从下手。

    后来看了题解,由于(n)​​​​​可以表示成(prodlimits{p^c})​​​​​,对于某个质因子(p),可得递推式(f(n)=(c+1) cdot f(frac{n}{p^c})+ccdot d(frac{n}{p^c})),其中(d(x))代表(x)​的约数个数。

    证明:

    对于(f(frac{n}{p^c}))​中任意的边((u,v))​,({(u,v),(pu,v),(p^2u,pv),...,(p^cu,p^{c-1}v)})属于(f(n));除此之外,对于(frac{n}{p^c})的任意约数(d)({(pd,d),(p^2d,pd),...,(p^cd,p^{c-1}d)})也属于(f(n))​。

    这个递推式乍看起来没啥用,但是它其实是符合min25允许的结构的。对于素数(p),有(f(p)=1)(f(p^c)=c)​,可以快速计算。

    min25统计答案时,是通过枚举最小质因子的方式统计,相比之下递推式只是多加了一个约数个数而已,而且约数个数是积性函数,也能用min25计算。因此在计算(f(x))​时同时计算(d(x))​的中间结果,在统计答案时加上去即可。

    原本我太死板,对min25理解太浅,以为只有符合条件的积性函数才可以用min25解决,现在看来只要可以拆分质因子计算贡献,就可能可以使用min25解决。

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1e6 + 10;
    const int M = 1145140019;
    const int INF = 0x3f3f3f3f;
    typedef long long ll;
    typedef pair<ll, ll> PII;
    #define endl '
    '
    #define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
    ll num[N], ans[N];
    ll id1[N], id2[N];
    ll pri[N];
    ll m, n;
    int cnt;
    bool isnp[N];
    
    inline ll qpow(ll a, ll b, ll m) {
        ll res = 1;
        while(b) {
            if(b & 1) res = (res * a) % m;
            a = (a * a) % m;
            b = b >> 1;
        }
        return res;
    }
    
    void init() {
        isnp[1] = 1;
        pri[cnt++] = 1;
        for(int i = 2; i < N; i++) {
            if(!isnp[i]) {
                pri[cnt++] = i;
                for(int j = 2 * i; j < N; j += i)
                    isnp[j] = 1;
            }
        }
    }
    
    int ID(ll x) { // 相当于hashmap,用于保存根号n个结果
        if(x <= m) return id1[x];
        return id2[n / x];
    }
    
    void solve(ll n) { // part 1
        int cur = 0;
        int mx = 0;
        m = 0;
        while(m * m <= n) {
            if(pri[mx] <= m) mx++;
            m++;
        }
        ll i = 1;
        while(i <= n) {
            num[cur] = n / i;
            ans[cur] = (num[cur] - 1) % M;
            if(num[cur] <= m) id1[num[cur]] = cur;
            else id2[n / num[cur]] = cur;
            cur++;
            i = n / (n / i) + 1;
        }
        for(int i = 1; i < mx; i++) {
            for(int j = 0; j < cur && 1ll * pri[i] * pri[i] <= num[j]; j++) {
                ans[j] -= (ans[ID(num[j] / pri[i])] - (i - 1)) % M;
                ans[j] %= M;
            }
        }
    }
    
    PII F(ll n, int k) { // part 2
        ll res = 0; // f(x)
        ll d = 0; // 约数个数
    
        for(int i = k; 1ll * pri[i] * pri[i] <= n; i++) {
            ll p = pri[i];
            int cnt = 1;
            while(p * pri[i] <= n) {
                auto par = F(n / p, i + 1);
                d += ((cnt + 1) * par.first % M + (cnt + 2)) % M;
                res += ((cnt + 1) * par.second % M + cnt * par.first % M + (cnt + 1)) % M;
                res %= M;
                d %= M;
                p = p * pri[i];
                cnt++;
            }
        }
        res += ans[ID(n)] - ((k - 1) ? ans[ID(pri[k - 1])] : 0) % M;
        d += 2 * (ans[ID(n)] - ((k - 1) ? ans[ID(pri[k - 1])] : 0)) % M;
        return {d % M, res % M};
    }
    
    
    
    int main() {
        IOS;
        init();
        int t;
        cin >> t;
        while(t--) {
            cin >> n;
            solve(n);
            cout << (F(n, 1).second % M + M) % M << endl;
        }
    }
    
  • 相关阅读:
    git 常用命令
    spring源码-事件&监听3.6
    spring源码-国际化-3.5
    spring源码-Aware-3.4
    spring源码-BeanPostProcessor-3.3
    springboot中对yaml文件的解析
    数组Array.sort()排序的方法
    【转】js 对象按照键值(不分区大小写)排序,生成签名方法
    【转】JS常用函数整合库 lutils
    VS2017调试出现异常浏览器直接关闭的解决办法
  • 原文地址:https://www.cnblogs.com/limil/p/15106447.html
Copyright © 2020-2023  润新知