题目链接

https://loj.ac/problem/3069

题解

复数真神奇。

一句话题意:令 \(f(x)\) 表示以原点 \((0, 0)\) 为圆心,半径为 \(x\) 的圆上的整点数量,求 \(\sum_\limits{i = 1}^N f(i)^k \bmod P\) 的值。

令 \(g(x) = \frac{f(x)}{4}\),那么我们需要求 \(\left(4^k\sum_\limits{i = 1}^Ng(i)^k\right) \bmod P\)。打表可得 \(g(x)\) 是一个积性函数,其证明如下:

首先显然有 \(g(1) = 1\)。

对于正整数 \(x \geq 2\),\(g(x)\) 有如下求法:

记 \(y = x^2\),假设 \(y\) 的唯一分解式中,形如 \(4n + 1(n \in \mathbb{N}^*)\) 的质数对应的指数分别为 \(\alpha_1, \alpha_2, \cdots, \alpha_m\),形如 \(4n + 3(n \in \mathbb{N})\) 的质数对应的指数分别为 \(\beta_1, \beta_2, \cdots, \beta_k\),那么有:

\[\begin{aligned}g(x) = \left(\prod_{i = 1}^m (\alpha_i + 1)\right) \left(\prod_{i = 1}^k [\beta_i 是偶数]\right)\end{aligned}
\]

关于上述 \(g(x)\) 的求法的具体原因及相关理论,可参考视频 隐藏在素数规律中的 π。包看包懂。

由于 \(y = x^2\),因此 \(y\) 的唯一分解式中任意质数的指数一定是偶数,即上述式子中后面部分 \(\left(\prod_\limits{i = 1}^k [\beta_i 是偶数]\right)\) 的值一定为 \(1\)。故有:

\[\begin{aligned}g(x) = \prod_{i = 1}^m (\alpha_i + 1)\end{aligned}
\]

对于互质的两个数 \(a, b\),显然 \(a^2, b^2\) 的唯一分解式中不会出现相同的质数,故此时有 \(g(ab) = g(a)g(b)\)。因此 \(g(x)\) 是一个积性函数。

\(g(x)\) 是积性函数那么 \(g(x)^k\) 显然也是积性函数。考虑使用 min_25 筛来求积性函数 \(g(x)^k\) 的前缀和。根据上面的理论,不难得出对于一个质数 \(p\),有

\[g(p^c)^k = \begin{cases}(2c + 1)^k, &p \bmod 4 = 1 \\ 1, &p \bmod 4 \neq 1 \end{cases}
\]

要注意的是,在算 \(g(p^c)\) 时,实际是对 \((p^c)^2\) 做唯一分解,因此当 \(p \bmod 4 = 1\) 时,\(g(p^c)\) 的值为 \(2c + 1\) 而不是 \(c + 1\)。

质数的任意次幂对应的函数值我们已经能够快速计算。接下来考虑如何求所有质数对应的函数值的前缀和。考虑先分别求出 \(1\sim n\) 内模 \(4\) 等于 \(1\) 的质数的数量以及模 \(4\) 等于 \(3\) 的质数的数量,不妨将两种质数对应的数量记为 \(S_1, S_3\),那么边界值(即将 \(2 \sim n\) 的所有数均视为质数时对应的值)显然是 \(S_1(n) = \left\lfloor\frac{n - 1}{4}\right\rfloor,\) \(S_3(n) = \left\lfloor\frac{n + 1}{4}\right\rfloor\)。考虑如何依次去掉以每一个 \(\geq 3\) 的质数作为最小质因子的所有数的贡献。注意到在模 \(4\) 意义下,有:当 \(a = 1\) 时,\(\begin{cases}a \times 1 = 1 \\ a \times 3 = 3\end{cases}\);当 \(a = 3\) 时,\(\begin{cases}a \times 1 = 3 \\ a \times 3 = 1\end{cases}\),因此对于每个 \(\geq 3\) 的质数 \(p\),\(S_1\) 与 \(S_3\) 的更新方式如下:

\[\begin{aligned}\text{if $p$ mod 4 = 1: }&\begin{cases} {S_1(x) \leftarrow S_1(x) - \left(S_1 (\left\lfloor\frac{x}{p}\right\rfloor) - S_1(p - 1)\right) \\S_3(x) \leftarrow S_3(x) - \left(S_3 (\left\lfloor\frac{x}{p}\right\rfloor) - S_3(p - 1)\right)} \end{cases} \\ \text{else: }&\begin{cases}{S_1(x) \leftarrow S_1(x) - \left(S_3 (\left\lfloor\frac{x}{p}\right\rfloor) - S_3(p - 1)\right) \\S_3(x) \leftarrow S_3(x) - \left(S_1 (\left\lfloor\frac{x}{p}\right\rfloor) - S_1(p - 1)\right)}\end{cases} \end{aligned}
\]

令 \(S(x)\) 为 \(1 \sim x\) 内的所有质数 \(p\) 对应的 \(g(p)^k\) 的值,那么有 \(S(x) = S_1(x) \times 3^k + S_3(x)\)。注意还应添加质数 \(2\) 的贡献。

时间复杂度为 \(O(\frac{n^{\frac{3}{4}}}{\log n})\)。

代码

#include<bits/stdc++.h>

using namespace std;

const int N = 345678;

long long n, k;
int mod, sq, ways[N];
vector<int> primes; class my_array {
public:
int a[N << 1]; int& operator [] (long long x) {
return x <= sq ? a[x] : a[sq + n / x];
}
}; my_array sump1, sump3, sump; void add(int& x, int y) {
x += y;
if (x >= mod) {
x -= mod;
}
} void sub(int& x, int y) {
x -= y;
if (x < 0) {
x += mod;
}
} int mul(int x, int y) {
return (long long) x * y % mod;
} int qpow(int v, long long p) {
int result = 1;
for (; p; p >>= 1, v = mul(v, v)) {
if (p & 1) {
result = mul(result, v);
}
}
return result;
} void sieve(int n) {
vector<bool> is_prime(n + 1, true);
for (int i = 2; i <= n; ++i) {
if (is_prime[i]) {
primes.push_back(i);
}
for (auto x : primes) {
if (i * x > n) {
break;
}
is_prime[i * x] = false;
if (i % x == 0) {
break;
}
}
}
} void min_25_sieve() {
vector<long long> values;
for (long long i = 1; i <= n; i = n / (n / i) + 1) {
values.push_back(n / i);
}
for (auto x : values) {
sump1[x] = (x - 1 >> 2) % mod;
sump3[x] = (x + 1 >> 2) % mod;
}
for (auto p : primes) {
if (p != 2) {
if (p % 4 == 1) {
for (auto x : values) {
if (x < (long long) p * p) {
break;
}
sub(sump1[x], (sump1[x / p] - sump1[p - 1] + mod) % mod);
sub(sump3[x], (sump3[x / p] - sump3[p - 1] + mod) % mod);
}
} else {
for (auto x : values) {
if (x < (long long) p * p) {
break;
}
sub(sump1[x], (sump3[x / p] - sump3[p - 1] + mod) % mod);
sub(sump3[x], (sump1[x / p] - sump1[p - 1] + mod) % mod);
}
}
}
}
for (auto x : values) {
sump[x] = (mul(sump1[x], ways[1]) + sump3[x] + (x >= 2)) % mod;
}
} int solve(long long n, int x) {
if (n <= 1 || (x <= primes.size() && primes[x - 1] > n)) {
return 0;
}
int result = (sump[n] - (x <= primes.size() ? sump[primes[x - 1] - 1] : sump[primes.back()]) + mod) % mod;
for (int i = x; i <= primes.size(); ++i) {
long long p = primes[i - 1], q = p;
if (p * q > n) {
break;
}
for (int j = 1; p * q <= n; ++j, q *= p) {
add(result, mul(ways[p % 4 == 1 ? j : 0], solve(n / q, i + 1)));
add(result, ways[p % 4 == 1 ? j + 1 : 0]);
}
}
return result;
} int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n >> k >> mod;
for (int i = 0; i < 34; ++i) {
ways[i] = qpow(i << 1 | 1, k);
}
sq = sqrt(n);
sq = max(sq, 2);
sieve(sq);
min_25_sieve();
cout << mul(qpow(4, k), (1 + solve(n, 1)) % mod) << '\n';
return 0;
}

LOJ3069. 「2019 集训队互测 Day 1」整点计数(min_25筛)的更多相关文章

  1. LOJ2476. 「2018 集训队互测 Day 3」蒜头的奖杯 & LOJ2565. 「SDOI2018」旧试题(莫比乌斯反演)

    题目链接 LOJ2476:https://loj.ac/problem/2476 LOJ2565:https://loj.ac/problem/2565 题解 参考照搬了 wxh 的博客. 为了方便, ...

  2. 【LOJ2461】「2018 集训队互测 Day 1」完美的队列(分块+双指针)

    点此看题面 大致题意: 让你维护\(n\)个有限定长度的队列,每次区间往队列里加数,求每次加完后的队列里剩余元素种类数. 核心思路 这道题可以用分块+双指针去搞. 考虑求出每个操作插入的元素在队列中被 ...

  3. @loj - 2461@ 「2018 集训队互测 Day 1」完美的队列

    目录 @description@ @solution@ @part - 0@ @part - 1@ @accepted code@ @details@ @description@ 小 D 有 n 个 ...

  4. 【loj2461】【2018集训队互测Day 1】完美的队列

    #2461. 「2018 集训队互测 Day 1」完美的队列 传送门: https://loj.ac/problem/2461 题解: 直接做可能一次操作加入队列同时会弹出很多数字,无法维护:一个操作 ...

  5. 【2018集训队互测】【XSY3372】取石子

    题目来源:2018集训队互测 Round17 T2 题意: 题解: 显然我是不可能想出来的……但是觉得这题题解太神了就来搬(chao)一下……Orzpyz! 显然不会无解…… 为了方便计算石子个数,在 ...

  6. 洛谷 P4463 - [集训队互测 2012] calc(多项式)

    题面传送门 & 加强版题面传送门 竟然能独立做出 jxd 互测的题(及其加强版),震撼震撼(((故写题解以祭之 首先由于 \(a_1,a_2,\cdots,a_n\) 互不相同,故可以考虑求出 ...

  7. 【纪中集训2019.3.27】【集训队互测2018】小A的旅行(白)

    题目 描述 ​ \(0-n-1\)的图,满足\(n\)是\(2\)的整数次幂, $ i \to j $ 有 $ A_{i,j} $ 条路径: ​ 一条路径的愉悦值定义为起点和终点编号的\(and\)值 ...

  8. UOJ#191. 【集训队互测2016】Unknown 点分治 分治 整体二分 凸包 计算几何

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ191.html 题目传送门 - UOJ191 题意 自行移步集训队论文2016中罗哲正的论文. 题解 自行 ...

  9. UOJ#191. 【集训队互测2016】Unknown

    题意:维护一个数列,每个元素是个二维向量,每次可以在后面加一个元素或者删除一个元素.给定P(x,y),询问对于[l,r]区间内的元素$S_i$,$S_i \times P$的最大值是多少. 首先简单地 ...

随机推荐

  1. 2.QWidget类

    简述: QWidget类是所有用户界面对象的基类. Widget是用户界面的基本单元:它从窗口系统接收鼠标,键盘和其他事件,并在屏幕上绘制自己. 每个Widget都是矩形的,它们按照Z-order进行 ...

  2. Laravel 多态关联使用的案例

    1.实现的功能,:短信发送,需要签名和模板审核,审核结果要插进审核记录表 2,在signature(签名表模型)和 template(模板表模型)添加多态对应关系代码其实一样,代码如下: 审核记录表需 ...

  3. 数据挖掘算法以及其实现zz

    实验一    分类技术及其应用 实习要求: 基于线性回归模型拟合一个班学生的学习成绩,建立预测模型.数据可由自己建立100个学生的学习成绩. 1)    算法思想: 最小二乘法 设经验方程是y=F(x ...

  4. foo是什么?

    在英文程序员社区里,foo bar baz这些词是常用于作为占位符而使用的.要查wiki的话,这项更合适:http://en.wikipedia.org/wiki/Metasyntactic_vari ...

  5. FZU 1977 Pandora adventure (DP)

    题意:给定一个图,X表示不能走,O表示必须要走,*表示可走可不走,问你多少种走的法,使得形成一个回路. 析: 代码如下: #pragma comment(linker, "/STACK:10 ...

  6. gcc中支持的一种字符串表示方式

    gcc支持的一种的字符串的表示形式 "xxx" "xxx" "xxx" 他会将这3个字符串连成一个并 且只会在最后的一个字符串末尾添加 '\ ...

  7. 排序:快速排序Quick Sort

    原理,通过一趟扫描将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序 ...

  8. ZOJ3708:Density of Power Network

    The vast power system is the most complicated man-made system and the greatest engineering innovatio ...

  9. [label][OS] 制作 U 盘安装 Windows 7

    U盘安装完美的WIN7操作系统教程 [编辑] 请使用正版系统   http://item.jd.com/965031.html   以保证您的电脑信息安全 此教程适用与 win7及win8 准备工作 ...

  10. GPS模块输出的NMEA数据ddmm.mmmm转换成dd.ddddd并在google Earth Pro中描点

      GPS模块输出的数据是NMEA格式,其中GPGGA字段包含我们需要的经纬度信息. 例:$GPGGA,092204.999,4250.5589,S,14718.5084,E,1,04,24.4,12 ...