P3768 简单的数学题 杜教筛+推式子
\(\color{#0066ff}{ 题目描述 }\)
由于出题人懒得写背景了,题目还是简单一点好。
输入一个整数n和一个整数p,你需要求出(\(\sum_{i=1}^n\sum_{j=1}^n ijgcd(i,j))~mod~p\),其中gcd(a,b)表示a与b的最大公约数。
\(\color{#0066ff}{输入格式}\)
一行两个整数p、n。
\(\color{#0066ff}{输出格式}\)
一行一个整数(\(\sum_{i=1}^n\sum_{j=1}^n ijgcd(i,j))~mod~p\)。
\(\color{#0066ff}{输入样例}\)
998244353 2000
\(\color{#0066ff}{输出样例}\)
883968974
\(\color{#0066ff}{数据范围与提示}\)
对于20%的数据,\(n \leq 1000\)。
对于30%的数据,\(n \leq 5000\)。
对于60%的数据,\(n \leq 10^6\),时限1s。
对于另外20%的数据,\(n \leq 10^9\),时限3s。
对于最后20%的数据,\(n \leq 10^{10}\),时限6s。
对于100%的数据,\(5 \times 10^8 \leq p \leq 1.1 \times 10^9\)且p为质数。
\(\color{#0066ff}{ 题解 }\)
这是一道神仙题qwq
开始推式子
题目要求
\]
老规矩,枚举gcd
\]
把d提出来
\]
后面把d弄出来
\]
利用\(\mu * i = e\)套进去
\]
即
\]
改为枚举倍数
\]
看到这个式子,大为欣喜,于是
\]
\]
\]
于是以为这题切掉了?????
我TM。。数据范围尼玛\(10^9\)
\(how\ \ \ to \ \ \ O(\sqrt n ^2)\)
显然要继续往下推
某巨佬有一手,pd换q的操作(原式为kd换q)
于是,先将原式变为
\]
考虑枚举q,那么里面的kd就可以提出来了
\]
这里面的d有点突兀qwq
\]
上面的式子是有问题的,因为枚举的\(q=kd\),那么k应该是q的因子,所以要改一下枚举,同时后面的可以写成平方形式
\]
然后可以把q提出来
\]
然后因为有
\]
因此代回去
\]
卧槽,继续
\]
我Fuck, \(O(\sqrt n)\) 我就不信还过不了??
\]
\]
杜教筛+数列分块就行了
注意各种取模,少一个都WAqwq
#include<bits/stdc++.h>
#define int long long
#define LL long long
LL in() {
char ch; LL x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
const int maxn = 4e6 + 10;
LL pri[maxn], phi[maxn], tot, mod;
LL six;
std::map<int, LL> mp;
bool vis[maxn];
LL ksm(LL x, LL y) {
LL re = 1LL;
while(y) {
if(y & 1) re = re * x % mod;
x = x * x % mod;
y >>= 1;
}
return re;
}
void predoit() {
mod = in();
six = ksm(6, mod - 2);
phi[1] = 1;
for(int i = 2; i < maxn; i++) {
if(!vis[i]) pri[++tot] = i, phi[i] = i - 1;
for(int j = 1; j <= tot && (LL)i * pri[j] < maxn; j++) {
vis[i * pri[j]] = true;
if(i % pri[j] == 0) {
phi[i * pri[j]] = phi[i] * pri[j];
break;
}
else phi[i * pri[j]] = phi[i] * (pri[j] - 1);
}
}
for(LL i = 2; i < maxn; i++) phi[i] = phi[i] * (i * i % mod) % mod;
for(LL i = 2; i < maxn; i++) (phi[i] += phi[i - 1]) %= mod;
}
LL getpfh(LL x) {
x %= mod;
LL ans = x;
ans = (ans * (x + 1)) % mod;
ans = (ans * ((x << 1LL) + 1)) % mod;
return ans * six % mod;
}
LL getlf(LL n) {
n %= mod;
n = (n * (n + 1) >> 1) % mod;
return n * n % mod;
}
LL getphi(LL n) {
if(n < maxn) return phi[n];
if(mp.count(n)) return mp[n];
LL ans = getlf(n);
for(LL l = 2, r; l <= n; l = r + 1) {
r = n / (n / l);
LL tot1 = ((getpfh(r) - getpfh(l - 1)) % mod + mod) % mod;
tot1 = tot1 * getphi(n / l) % mod;
ans = ((ans - tot1) % mod + mod) % mod;
}
return mp[n] = ans;
}
LL getsum(LL x) {
x %= mod;
LL ans = (x * (x + 1) >> 1LL) % mod;
return ans * ans % mod;
}
void work(LL n) {
LL ans = 0;
for(LL l = 1, r; l <= n; l = r + 1) {
r = n / (n / l);
LL tot1 = ((getphi(r) - getphi(l - 1)) % mod + mod) % mod;
tot1 = (tot1 * getsum(n / l)) % mod;
ans = (ans + tot1) % mod;
}
printf("%lld", (ans % mod + mod) % mod);
}
signed main() {
predoit();
work(in());
return 0;
}
P3768 简单的数学题 杜教筛+推式子的更多相关文章
- luogu P3768 简单的数学题 杜教筛 + 欧拉反演 + 逆元
求 $\sum_{i=1}^{n}\sum_{j=1}^{n}ijgcd(i,j)$ 考虑欧拉反演: $\sum_{d|n}\varphi(d)=n$ $\Rightarrow \sum_{i ...
- P3768 简单的数学题 [杜教筛,莫比乌斯反演]
\[\sum_{i=1}^{n}\sum_{j=1}^{n} ij\gcd(i,j)\] \[=\sum_{d=1}^{n} d \sum_{i=1}^{n}\sum_{j=1}^{n} ij[\gc ...
- [luogu3768] 简单的数学题 [杜教筛]
题面: 传送门 实际上就是求: 思路: 看到gcd就先反演一下,过程大概是这样: 明显的一步反演 这里设,S(x)等于1到x的和 然后把枚举d再枚举T变成先枚举T再枚举其约数d,变形: 后面其中两项展 ...
- 【luogu3768】简单的数学题 欧拉函数(欧拉反演)+杜教筛
题目描述 给出 $n$ 和 $p$ ,求 $(\sum\limits_{i=1}^n\sum\limits_{j=1}^nij\gcd(i,j))\mod p$ . $n\le 10^{10}$ . ...
- 莫比乌斯反演/线性筛/积性函数/杜教筛/min25筛 学习笔记
最近重新系统地学了下这几个知识点,以前没发现他们的联系,这次总结一下. 莫比乌斯反演入门:https://blog.csdn.net/litble/article/details/72804050 线 ...
- 【51NOD 1847】奇怪的数学题(莫比乌斯反演,杜教筛,min_25筛,第二类斯特林数)
[51NOD 1847]奇怪的数学题(莫比乌斯反演,杜教筛,min_25筛,第二类斯特林数) 题面 51NOD \[\sum_{i=1}^n\sum_{j=1}^nsgcd(i,j)^k\] 其中\( ...
- 【刷题】洛谷 P3768 简单的数学题
题目描述 由于出题人懒得写背景了,题目还是简单一点好. 输入一个整数n和一个整数p,你需要求出(\(\sum_{i=1}^n\sum_{j=1}^n ijgcd(i,j))~mod~p\),其中gcd ...
- 洛谷 P3768 简单的数学题
https://www.luogu.org/problemnew/show/P3768 化简一下式子,就是$\sum_{d=1}^ncalc(d)d^2\varphi(d)$ 其中$calc(d)=\ ...
- LOJ# 572. 「LibreOJ Round #11」Misaka Network 与求和(min25筛,杜教筛,莫比乌斯反演)
题意 求 \[ \sum_{i = 1}^{n} \sum_{i = 1}^{n} f(\gcd(i, j))^k \pmod {2^{32}} \] 其中 \(f(x)\) 为 \(x\) 的次大质 ...
随机推荐
- Oracle RMAN 学习:演练进阶篇
Oracle RMAN 学习:演练进阶篇 5 Rman备份演练进阶篇 5.1 是否选择增量备份 Backup命令生成的备份集中只备份了那些使用了的数据块,备份集实际大小已经较目标数据库的数据文件小了很 ...
- mybatis学习7 实战项目
自己写一个实战项目,最好和hibernate做对比.
- Python函数(一)-return返回值
定义一个函数可以在最后加上return返回值,方便查看函数是否运行完成和返回函数的值 # -*- coding:utf-8 -*- __author__ = "MuT6 Sch01aR&qu ...
- VC用Beep整几首歌听听~~~
//生日快乐歌 #include "stdafx.h"#include <windows.h>void main(void) { unsigned FR ...
- Ok6410裸机驱动学习(三)C语言内嵌汇编
1.C语言内嵌汇编使用方法 C内嵌汇编以关键字”_asm_或asm开始,下辖4个部分,各部分之间用“:”分开,第一部分是必须写的,后面3个部分可以省略,但是分号:不能省略 优化后的代码 2.汇编程序框 ...
- 导入android studio项目,编译失败
使用android studio 打开studio 工程,编译的时候报错: “ INFO - .project.GradleProjectResolver - Gradle project resol ...
- echarts柱状图每个柱子显示不同颜色,并且能够实现点击每种颜色影藏对应柱子的功能
---------------------------------------------------------代码区---------------------------------------- ...
- c语言实战: 计算时间差
计算时间差有两种,一种是把时间都转化为分钟数,一种是把时间都转化为小时,后者是会用到除法所以不可避免产生浮点数,所以我们选择转化为分钟数来计算. //题目:给定两个时间点计算它们的时间差,比如,1:5 ...
- python3-打印一个进度条
# Auther: Aaron Fan import sys,time for i in range(30): #打印一个#号,这种方法打印不会自动换行 sys.stdout.write('#') # ...
- JavaWeb_内省(Instrospector)
内省是什么? 开发框架时,经常需要使用java对象的属性来封装程序的数据,每次都是用反射技术完成此类操作过于麻烦,所以sun公司开发了一套API,专门用于操作Java对象的属性. 什么是Java对象的 ...