@hdu - [email protected] Function

目录

  • @[email protected]
  • @[email protected]
  • @accepted [email protected]
  • @[email protected]

@[email protected]

给定 n,求:
\[\sum_{i=1}^{n}gcd(\lfloor^3\sqrt{i}\rfloor, i)\mod 998244353\]

Input
第一行包含一个整数 T(1≤T≤11) 描述数据组数。
接下来 T 行,每行一个整数 n (1≤n≤10^21) 描述询问。

Output
对于每组询问,输出答案 mod 998244353。

Sample Input
10
64
180
526
267
775
649
749
908
300
255
Sample Output
103
327
1069
522
1693
1379
1631
1998
606
492

@[email protected]

考虑 \(\lfloor^3\sqrt{n}\rfloor\) 其实只有 10^7 种取值,令 \(x =\lfloor^3\sqrt{n}\rfloor\),我们的问题其实是在求:
\[ans=\sum_{i=1}^{x-1}\sum_{j=i^3}^{(i+1)^3-1}gcd(i, j) + \sum_{j=x^3}^{n}gcd(x, j)\]

我们现在考虑怎么求 \(f(n, i)=\sum_{j=1}^{n}gcd(i, j)\),然后用前缀和相减的方法搞一搞。
考虑一波反演变成 \(f(n, i)=\sum_{p|i}\sum_{d|p}\lfloor\frac{n}{p}\rfloor*\mu(\frac{p}{d})*d\)。

注意到 \(i|i^3, i|(i+1)^3-1\),放在上式相当于 \(n=i^3 或 (i+1)^3-1\),于是可以得到 \(p|n\)。
由此,考虑对式子进行进一步地变形,得到 \(f(n, i)=n*\sum_{p|i}\sum_{d|p}\frac{d}{p}*\mu(\frac{p}{d})\)。

令整数 \(a = \frac{p}{d}\)。考虑对于某个 i,一共有 \(\sigma(\frac{i}{a})\) 对 (p, d) 满足 \(a = \frac{p}{d}\)。
所以得到 \(f(n, i)=n*\sum_{a|i}\frac{\mu(a)}{a}*\sigma(\frac{i}{a})\)。
然后后面那个 \(\sum_{a|i}\frac{\mu(a)}{a}*\sigma(\frac{i}{a})\) 显然是个积性函数,筛一筛就好了,不妨令为 g(i)。

现在答案的表达式变为:
\[ans=\sum_{i=1}^{x-1}(((i+1)^3-1)*g(i) - i^3*g(i) + gcd(i, i^3)) + \sum_{j=1}^{n}gcd(x, j) - g(x)*x^3 + gcd(x, x^3)\]

因为 gcd(i, i^3) = i,所以只需要一个等差数列求和公式套上去就可以解决这些项了。那些与 n 无关的项可以直接预处理。

现在只剩下 \(\sum_{j=1}^{n}gcd(x, j)\) 这一项需要求解。因为 \(x | n\) 不一定成立,所以上面的推导不一定成立。
考虑回到最初的反演式:\(\sum_{j=1}^{n}gcd(x, j) = \sum_{p|x}\sum_{d|p}\lfloor\frac{n}{p}\rfloor*\mu(\frac{p}{d})*d\)
假如枚举出 p,那么剩下的 \(\sum_{d|p}\mu(\frac{p}{d})*d\) 就又是个积性函数了,筛就完事儿了。

最后只需要枚举因数,因此复杂度是 \(O(10^7 + \sqrt{10^7}*T)\)。好像比正解要优秀些?

@accepted [email protected]

#include<cstdio>
const int MAXN = int(1E7);
const int MOD = 998244353;
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 pow_mod(int b, int p) {
    int ret = 1;
    while( p ) {
        if( p & 1 ) ret = 1LL*ret*b%MOD;
        b = 1LL*b*b%MOD;
        p >>= 1;
    }
    return ret;
}
int club(__int128 x) {
    int l = 1, r = int(1E7);
    while( l < r ) {
        int mid = (l + r + 1) >>1;
        __int128 y = mid;
        if( y*y*y <= x ) l = mid;
        else r = mid - 1;
    }
    return l;
}
int inv[MAXN + 5], f[MAXN + 5], g[MAXN + 5], h[MAXN + 5];
int prm[MAXN + 5], low[MAXN + 5], pcnt = 0;
int gcd(int a, int b) {
    return (b == 0) ? a : gcd(b, a%b);
}
void init() {
    inv[1] = 1;
    for(int i=2;i<=MAXN;i++)
        inv[i] = MOD - 1LL*inv[MOD%i]*(MOD/i)%MOD;
    low[1] = f[1] = g[1] = 1;
    for(int i=2;i<=MAXN;i++) {
        if( !low[i] ) {
            low[i] = i, prm[++pcnt] = i;
            f[i] = (2 + MOD - inv[i])%MOD;
            g[i] = (i - 1)%MOD;
            long long p = 1LL*i*i;
            for(int j=2;p<=MAXN;p*=i,j++)
                low[p] = p, f[p] = (j + 1 + (MOD - 1LL*inv[i]*j%MOD))%MOD, g[p] = p/i*(i-1);
        }
        for(int j=1;1LL*i*prm[j]<=MAXN;j++) {
            if( i % prm[j] == 0 ) {
                if( i != low[i] ) {
                    low[i*prm[j]] = low[i]*prm[j];
                    f[i*prm[j]] = 1LL*f[i/low[i]]*f[prm[j]*low[i]]%MOD;
                    g[i*prm[j]] = 1LL*g[i/low[i]]*g[prm[j]*low[i]]%MOD;
                }
                break;
            }
            else {
                low[i*prm[j]] = prm[j];
                f[i*prm[j]] = 1LL*f[i]*f[prm[j]]%MOD;
                g[i*prm[j]] = 1LL*g[i]*g[prm[j]]%MOD;
            }
        }
    }
    for(int i=1;i<=MAXN;i++) {
        int tmp = (1LL*(i+1)*(i+1)%MOD*(i+1)%MOD + MOD - 1)%MOD;
        h[i] = 1LL*f[i]*tmp%MOD;
        h[i] = (h[i-1] + h[i])%MOD;
        tmp = 1LL*i*i%MOD*i%MOD;
        f[i] = 1LL*f[i]*tmp%MOD;
        f[i] = (f[i-1] + f[i])%MOD;
    }
}
int main() {
    init();
    int T; scanf("%d", &T);
    while( T-- ) {
        __int128 n; read(n);
        int p = club(n), ans = 1LL*p*(p+1)%MOD*inv[2]%MOD;
        for(int i=1;i*i<=p;i++) {
            if( p % i == 0 ) {
                ans = (ans + 1LL*g[i]*((n/i)%MOD)%MOD)%MOD;
                if( i*i != p )
                    ans = (ans + 1LL*g[p/i]*((n/(p/i))%MOD)%MOD)%MOD;
            }
        }
        ans = (ans + MOD - f[p])%MOD;
        printf("%d\n", (ans + h[p-1])%MOD);
    }
}

@[email protected]

因为怕 __int128 没办法用 cmath 里的 pow 函数,所以自己手写了个二分(居然没有问题)

考场上因为某个地方的 n/i 写成了 n/(p/i),没有调出来然后 GG 了。考后 debug 一会儿就出来了 QAQ。。。

原文地址:https://www.cnblogs.com/Tiw-Air-OAO/p/11304899.html

时间: 2024-08-30 10:17:54

@hdu - [email protected] Function的相关文章

@hdu - [email&#160;protected] Problem A.Alkane

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 求包含 n 个碳的烷烃与烷基的同分异构体个数 mod 998244353. 如果你没学过有机化学,你可以认为烷烃是 n 个点且每个点度数 <= 4 的无根树:烷基是 n 个点且每个点儿子个数 <= 3 的有根树. 原题传送门. @[email protected] 先考虑有根树的情况

@hdu - [email&#160;protected] Rigid Frameworks

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 如果对于一个平面图,将边看成火柴棍,将点看成用橡皮筋将木棍的头绑在一起(请自行脑补).如果这个平面图不能够改变形状,称这个平面图为刚体图. 如下图中只有 D 不是刚体图. 给定一个 n*m 的方格图,你可以在某些方格的对角线上加支撑木棍以保持它的形状不变. 问让一个 n*m 的方格图变

@hdu - [email&#160;protected] Paint Pearls

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 给定一个长度为 n 的序列,每一个位置有一个目标颜色,初始所有位置都没有颜色. 每次操作可以选择一个区间,将这个区间内的位置的颜色改为其目标颜色,代价是区间内不同的目标颜色数量^2. 求将所有位置改为目标颜色的最小代价. Input 多组数据. 每组数据第一行一个整数 n(1 ≤ n

@codeforces - [email&#160;protected] Function

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 已知 a 序列,并给定以下关系: \[\begin{cases} f(1, j) = a_j & (1 \le j \le n) \f(i, j) = \min\{f(i - 1, j), f(i - 1, j - 1)\} + a_j & (2 \le i \le j \le

@hdu - [email&#160;protected] Subsequence

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 给定如下计算序列权值的函数: 对于一个由三元组 (cost0, cost1, color) 组成的序列 A,求通过以上函数计算出来的第 k 大的子序列的权值. Input 第一行一个整数 t,表示数据组数. 对于每组数据,第一行包含两个整数 n, k. 接下来 n 行,每行三个整数 c

@hdu - [email&#160;protected] Counting Stars

目录 @[email protected] @[email protected] @accepted [email protected] @[email protected] @[email protected] 给定一个 n 点 m 边的无向图(无重边自环),求有多少子图形如,包含 4 个点 {A, B, C, D} 与 6 条边 {AB, BC, CD, DA, AC}. 原题链接. @[email protected] 一个并不常用的黑科技:三元环计数. mark一下博客地址. 注意到题目

makefile 中 [email&#160;protected] $^ %&lt; 使用

这篇文章介绍在LINUX下进行C语言编程所需要的基础知识.在这篇文章当中,我们将会学到以下内容: 源程序编译 Makefile的编写 程序库的链接 程序的调试 头文件和系统求助 1.源程序的编译 在Linux下面,如果要编译一个C语言源程序,我们要使用GNU的gcc编译器. 下面我们以一个实例来说明如何使用gcc编译器. 假设我们有下面一个非常简单的源程序(hello.c): int main(int argc,char **argv) { printf("Hello Linux\n"

[email&#160;protected]一个高效的配置管理工具--Ansible configure management--翻译(七)

如无书面授权,请勿转载 Larger Projects Until now, we have been looking at single plays in one playbook file. This approach will work for simple infrastructures, or when using Ansible as a simple deployment mechanism. However, if you have a large and complicated

[email&#160;protected]:php

curl 获取页面信息 function curl_get_content($url){ $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查 curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (X11; Linux x86_64) App