zoukankan      html  css  js  c++  java
  • (2019杭电多校第一场)hdu6588 Function

    题意

    \[\sum_{i=1}^ngcd(\lfloor\sqrt[3]i\rfloor, i) \]

    \(n \leq 10^{21}\)

    官方题解讲的大部分都很明白了,主要是有两个地方有点莫名其妙,想了整整七天才想明白。。。是我太菜了

    \(m=\lfloor\sqrt[3]n\rfloor\)

    原式

    \(=\sum_{a=1}^{m-1}\sum_{i=a^3}^{(a+1)^3-1}gcd(a,i)+\sum_{i=m^3}^ngcd(m,i)\)

    \(f(a, n)=\sum_{i=1}^ngcd(a,i)\)

    \(f(a,n)=\sum_{d|a}d\sum_{i=1}^{\frac{n}{d}}[gcd(\frac{a}{d},i)==1]=\sum_{d|a}d\sum_{e|\frac{a}{d}}\mu(e)\lfloor\frac{n}{de}\rfloor\)

    这个是反演演出来的。。。理解成容斥也可以。。。

    然后第一个摸不着头脑的地方是下一步。。。下一步最关键的是要去设\(T=de\),观察到上式枚举的\(d,e\)\(a\)的两个“不相交”的因子(意会一下XD)

    所以\(T|a,d|T\),因此实际上可以变换成

    \(f(a,n)=\sum_{T|a}\sum_{d|T}d\mu(\frac{T}{d})\lfloor\frac{n}{T}\rfloor=\sum_{T|a}\lfloor\frac{n}{T}\rfloor\sum_{d|T}d\mu(\frac{T}{d})\)

    后面那个是个公式,等于\(\varphi(T)\),所以\(f(a,n) = \sum_{T|a}\lfloor\frac{n}{T}\rfloor\varphi(T)\)

    这个\(O(\sqrt n)\)搞定

    接下来是答案的前半部分,代入\(f(a,(a+1)^3-1)-f(a,a^3-1)\)

    \(\sum_{a=1}^{m-1}\sum_{T|a}\varphi(T)(\lfloor\frac{(a+1)^3-1}{T}\rfloor-\lfloor\frac{a^3-1}{T}\rfloor)\)

    下一步设\(a=bT\),交换两个求和符号也有点摸不着头脑。。。意思就是从先枚举\(a\)改为先枚举\(T\)小于等于\(m-1\)再枚举小于等于\(m-1\)\(T\)的倍数\(a\),也就相当于枚举\(b\)从1到\(\lfloor\frac{m-1}{T}\rfloor\).

    然后那一通拆括号变形计算就略了,设\(y = \lfloor\frac{m-1}{T}\rfloor\)最后答案是

    \[\sum_{T=1}^{m-1}\varphi(T)[3T\sum_{b=1}^yb^2+3\sum_{b=1}^yb+\sum_{b=1}^y1] \]

    里面的三个都直接套公式求和就搞定了。。

    我写的太丑了,全改成int128会T...还要注意一下能用ll就别用int128

    #include <bits/stdc++.h>
    #define LL long long
    #define MAXN 10000000
    using namespace std;
    const LL mod = 998244353;
    const LL inv6 = 166374059, inv2 = 499122177;
    LL gcd(LL a, LL b)
    {
        return b?gcd(b, a%b):a;
    }
    
    int prime[MAXN + 8];
    int phi[MAXN + 8];
    bool notprime[MAXN + 8];
    int ind = 0;
    void getprime()
    {
        notprime[1] = true;
        phi[1] = 1;
        for (int i = 2; i <= MAXN; ++i)
        {
            if (!notprime[i])
            {
                prime[++ind] = i;
                phi[i] = i - 1;
            }
            for (int j = 1; j <= ind && i * prime[j] <= MAXN; ++j)
            {
                notprime[i * prime[j]] = true;
                if (i % prime[j] == 0)
                {
                    phi[i * prime[j]] = phi[i] * prime[j];
                    break;
                }
                phi[i * prime[j]] = phi[i] * (prime[j] - 1);
            }
        }
    }
    __int128_t n;
    
    LL tripleroot(__int128_t n)
    {
        __int128_t l = 1, r = 100000000;
        while (l < r)
        {
            __int128_t mid = (l + r) / 2;
            if (mid * mid * mid < n)
                l = mid + 1;
            else
                r = mid;
        }
        return (LL)(l - (l * l * l > n));
    }
    
    LL f(LL a, __int128_t n)
    {
        LL ret = 0;
        for (LL T = 1; T * T <= a; ++T)
        {
            if (a % T) continue;
            ret = (ret + (n / T) * phi[T] % mod) % mod;
            if (T * T != a)
            {
                LL B = a / T;
                ret = (ret + (n / B) * phi[B] % mod) % mod;
            }
        }
        return ret;
    }
    
    template <class T>
    void read(T &x) {
        static char ch;static bool neg;
        for(ch=neg=0;ch<'0' || '9'<ch;neg|=ch=='-',ch=getchar());
        for(x=0;'0'<=ch && ch<='9';(x*=10)+=ch-'0',ch=getchar());
        x=neg?-x:x;
    }
    int main()
    {
        getprime();
        int __;
        read(__);
        while (__--)
        {
            read(n);
            if (n <= 7)
            {
                LL ret = 0;
                for (LL i = 1; i <= n; ++i)
                    ret += gcd(1, i);
                cout << ret << endl;
                continue;
            }
            LL m = tripleroot(n);
            LL ans = (f(m, n) - f(m, (__int128_t)m * m * m - 1) + mod) % mod;
            for (LL T = 1; T <= m - 1; ++T)
            {
                LL y = (m - 1) / T;
                ans = (ans + phi[T] * (((3 * T % mod * y % mod * (y + 1) % mod * (2 * y + 1) % mod * inv6 % mod)
                                       + (3 * y % mod * (y + 1) % mod * inv2 % mod)
                                       + y) % mod) % mod) % mod;
            }
            cout << ans << endl;
        }
    }
    
  • 相关阅读:
    类和对象
    循环结构(二)
    循环结构(一)
    Java数据类型
    对Java的初识
    函数的作用域、作用域链以及return关键字
    var、fucntion关键字优先级问题
    JavaScript中定义函数的几种方式
    JavaScript变量名与函数名的命名规范
    使用JavaScript分别实现4种样式的九九乘法表(1X1分别在左上、左下、右上、右下)
  • 原文地址:https://www.cnblogs.com/zhugezy/p/11272644.html
Copyright © 2011-2022 走看看