hdu 6588 Function (數論+莫比烏斯反演)

 

\sum_{i=1}^n \gcd(\sqrt[3]{i},i) \mod 998244353


首先考慮分塊,按照 \sqrt[3]{n} 的大小分塊得到 \sum_{i=1}^{\sqrt[3]{n}-1}\sum_{j=i^3}^{(i+1)^3-1}\gcd(i,j)+\sum_{i=\sqrt[3]{n}^3}^n\gcd(\sqrt[3]{n},i)\mod 998244353

設 F(x,n)=\sum_{i=1}^n\gcd(x,i),化簡得到 F(x,n)=\sum_{T|x}\phi_T \left \lfloor \frac{n}{T} \right \rfloor     (化簡過程無法證明,也看不懂題解,我太菜了)

所以原式可以化成

=\sum_{i=1}^{\sqrt[3]{n}-1} (F(i,(i+1)^3-1)-F(i,i^3-1))+(F(\sqrt[3]{n},n)-F(\sqrt[3]{n},\sqrt[3]{n}^3-1))

=\sum_{i=1}^{\sqrt[3]{n}-1} \sum_{T|i}\phi_T(\left \lfloor \frac{(i+1)^3-1}{T}\right \rfloor-\left \lfloor \frac{i^3-1}{T}\right \rfloor)+\sum_{T|\sqrt[3]{n}}\phi_T(\left \lfloor \frac{n}{T} \right \rfloor - \left \lfloor \frac{\sqrt[3]{n}^3-1}{T} \right \rfloor)

右邊直接枚舉因子,可以在 O(\sqrt[6]{n}) 求出來,所以我們考慮化簡左邊的式子,枚舉 T 得到 =\sum_{T=1}^{\sqrt[3]{n}-1}\phi_T \sum_{i=1}^{\frac{\sqrt[3]{n}-1}{T}} (\left \lfloor \frac{(iT+1)^3-1}{T}\right \rfloor-\left \lfloor \frac{(iT)^3-1}{T}\right \rfloor)

=\sum_{T=1}^{\sqrt[3]{n}-1}\phi_T \sum_{i=1}^{\frac{\sqrt[3]{n}-1}{T}} (\left \lfloor \frac{i^3T^3+3i^2T^2+3iT}{T}\right \rfloor-\left \lfloor \frac{i^3T^3-1}{T}\right \rfloor)

=\sum_{T=1}^{\sqrt[3]{n}-1}\phi_T \sum_{i=1}^{\frac{\sqrt[3]{n}-1}{T}} (\left \lfloor i^3T^2+3i^2T+3i \right \rfloor-\left \lfloor i^3T^2-\frac{1}{T} \right \rfloor)

=\sum_{T=1}^{\sqrt[3]{n}-1}\phi_T \sum_{i=1}^{\frac{\sqrt[3]{n}-1}{T}} (3i^2T+3i+1)

=\sum_{T=1}^{\sqrt[3]{n}-1}(\sum_{i=1}^{\frac{\sqrt[3]{n}-1}{T}} i^2 + 3\phi_T \sum_{i=1}^{\frac{\sqrt[3]{n}-1}{T}} i +\phi_T \sum_{i=1}^{\frac{\sqrt[3]{n}-1}{T}} 1)

用常見的整除分塊,預處理 \phi_T, \ \phi_T*T 前綴和,就可以在 O(\sqrt[6]{n}) 求出來

所以原式 =\sum_{T=1}^{\sqrt[3]{n}-1}(\sum_{i=1}^{\frac{\sqrt[3]{n}-1}{T}} i^2 + 3\phi_T \sum_{i=1}^{\frac{\sqrt[3]{n}-1}{T}} i +\phi_T \sum_{i=1}^{\frac{\sqrt[3]{n}-1}{T}} 1)+\sum_{T|\sqrt[3]{n}}\phi_T(\left \lfloor \frac{n}{T} \right \rfloor - \left \lfloor \frac{\sqrt[3]{n}^3-1}{T} \right \rfloor)

整體複雜度 O(\sqrt[3]{n}+T\sqrt[6]{n})

#include <bits/stdc++.h>
#define ll long long //T了就換int 試試
#define int128 __int128
#define sc scanf
#define pr printf
using namespace std;
const int MAXN = 1e7 + 5;//用板子前先改範圍

bool check[MAXN + 10];//值爲 false 表示素數,值爲 true 表示非素數
int phi[MAXN + 10];//歐拉函數表
int prime[MAXN + 10];//連續素數表
//int mu[MAXN + 10];//莫比烏斯函數
int tot;//素數的個數(從0開始
ll sub[MAXN + 10];
ll subi[MAXN + 10];
const ll mod = 998244353;
const ll inv2 = (mod + 1) / 2;
const ll inv6 = (mod + 1) / 6;
void jzk()
{
    //memset(check, false, sizeof(check));
    phi[1] = 1;
    //mu[1] = 1;
    check[1] = true;
    tot = 0;
    for (int i = 2; i < MAXN; i++)
    {
        if (!check[i])
        {
            prime[tot++] = i;
            phi[i] = i - 1;
            //mu[i] = -1;
        }
        for (int j = 0; j < tot; j++)
        {
            if (i * prime[j] >= MAXN)
                break;
            check[i * prime[j]] = true;
            if (i % prime[j] == 0)
            {
                phi[i * prime[j]] = phi[i] * prime[j];
                //mu[i * prime[j]] = 0;
                break;
            }
            else
            {
                phi[i * prime[j]] = phi[i] * (prime[j] - 1);
                //mu[i * prime[j]] = -mu[i];
            }
        }
    }
    for (int i = 1; i < MAXN; i++)
    {
        sub[i] = (sub[i - 1] + phi[i]) % mod;
        subi[i] = (subi[i - 1] + (ll)phi[i] * i) % mod;
    }
}
ll ck(int128 n)
{
    int128 l = 1, r = /*1e4;*/1e7;
    while (l + 1 < r)
    {
        int128 k = (l + r) / 2;
        if (k * k * k > n)
            r = k;
        else
            l = k;
    }
    if (r * r * r <= n)
        l = r;
    return (ll)l;
}
ll calc2(ll n)
{
    return n * (n + 1) % mod * (2 * n + 1) % mod * inv6 % mod;
}
ll calc1(ll n)
{
    return n * (n + 1) % mod * inv2 % mod;
}
ll calc0(ll n)
{
    return n;
}
inline int128 read()
{
    int128 X = 0, w = 0; char ch = 0;
    while (!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }
    while (isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
    return w ? -X : X;
}
inline void print(int128 x)
{
    if (x < 0) { putchar('-'); x = -x; }
    if (x > 9) print(x / 10);
    putchar(x % 10 + '0');
}
int main()
{
    //freopen("test1.in","r",stdin);
    jzk();
    int T;
    sc("%d", &T);
    while (T--)
    {
        int128 n;
        n = read();
        //sc("%lld", &n);
        int128 ans = 0;
        ll n3 = ck(n);
        int128 n33 = (int128)n3 * n3 * n3;
        ll j;
        for (ll T = 1; T <= n3 - 1; T = j + 1)
        {
            /*ll res = (3 * T * calc2((n3 - 1) / T) % mod + 3 * calc1((n3 - 1) / T) % mod + calc0((n3 - 1) / T)) % mod;
            res = res * phi[T];*/
            j = (n3 - 1) / ((n3 - 1) / T);
            ll res = ((subi[j] - subi[T - 1] + mod) * 3 * calc2((n3 - 1) / T) % mod + (sub[j] - sub[T - 1] + mod) * 3 * calc1((n3 - 1) / T) % mod + (sub[j] - sub[T - 1] + mod) * calc0((n3 - 1) / T) % mod) % mod;
            ans = (ans + res) % mod;
        }
        for (ll T = 1; T * T <= n3; T++)
        {
            if (n3 % T == 0)
            {
                ans = (ans + phi[T] * ((n / T) - ((n33 - 1) / T) + mod)) % mod;
                if (T * T != n3)
                    ans = (ans + phi[n3 / T] * ((n / (n3 / T)) - ((n33 - 1) / (n3 / T)) + mod)) % mod;
            }
        }
        print(ans);
        putchar('\n');
        //pr("%lld\n", ans);
    }
}

 

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