51nod - 1188 - 最大公约数之和 V2 - 数论
https://www.51nod.com/Challenge/Problem.html#!#problemId=1188
求\(\sum\limits_{i=1}^{n-1}\sum\limits_{j=i+1}^{n}gcd(i,j)\)
首先交换求和\(\sum\limits_{j=2}^{n}\sum\limits_{i=1}^{j-1}gcd(i,j)=\sum\limits_{j=2}^{n}\sum\limits_{i=1}^{j}gcd(i,j)-j\)
像之前那样用莫比乌斯反演搞出
\(\sum\limits_{g=1}^{n}g\sum\limits_{i=1}^{\lfloor\frac{n}{g}\rfloor}{\varphi(i)}, (\varphi(1)=0)\)
或者
\(\sum\limits_{g=1}^{n}g\sum\limits_{i=1}^{\lfloor\frac{n}{g}\rfloor}{\mu(i)}*{\lfloor\frac{n}{i*g}\rfloor}^2\)
都是T了,说明单次回答的复杂度非常感人,原因是因为跟n有关就逃不了分块。
所以分块的复杂度还是太高了。
然后惊人的事情发生了。
这道题和前面的不一样的地方在于,他的n其实没有前面的大,只是多!
分块的意义在于加快单次回答的速度,所以才把g提了出来分块,现在不太合适。
正解,先求解:
\(\sum\limits_{i=1}^{n}gcd(i,n)\)
这个东西可以枚举g:
\(\sum\limits_{g=1}^{n}g\sum\limits_{i=1}^{n}[gcd(i,n)==g]\)
\(\sum\limits_{g=1}^{n}g\sum\limits_{i=1}^{\lfloor\frac{n}{g}\rfloor}[gcd(i,\lfloor\frac{n}{g}\rfloor)==1]\)
\(\sum\limits_{g=1}^{n}g\varphi(\lfloor\frac{n}{g}\rfloor)\)
这个有什么不对呢?其实没什么不对,就是不好。因为gcd必定是整除n的,所以可以:
\(\sum\limits_{g|n}g\varphi(\frac{n}{g})\)
这明显就是一个积性函数,记为 \(p(n)\) ,处理好就可以了。原式:
\(\sum\limits_{j=2}^{n}p(j)-j\)
这个式子 \(p(n)\) 用埃筛已经足够了,因为是5e6的数据量,1400ms/2000ms跑过去了。但是我在想会不会有线性的筛法。
2019/6/7早上试了很多种之后,发现还是直接利用积性函数的结论最简单,对于每个合数记录他的最小质因子及其幂次,然后一除就得到两个互质的因数。
问题在于纯p的幂次一除就变成没有了。也就是别人的博客说的 \(p^k\) 要特殊处理,想到上面这个式子是一个狄利克雷卷积,对于纯p的幂次只要从他的低1次转移过来就可以了。
最后套上快读快写狗掉榜首!需要注意的是我准备的线性筛模板里多用了0.25倍空间,其实真的可以充分利用的。比如这个的话pk肯定不是0,那么就用pk来做判断就可以了。
所以说的确是空间换时间,多了0.5倍的空间省去一个logn倍。200ms/2000ms稳得一笔。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline int read() {
int x=0;
char c=getchar();
while(c<'0'||c>'9')
c=getchar();
do {
x=(x<<3)+(x<<1)+c-'0';
c=getchar();
} while(c>='0'&&c<='9');
return x;
}
inline void write(ll x) {
//printf("%lld\n",x);
if(x>9) {
write(x/10);
}
putchar(x%10+'0');
return;
}
const int MAXN=5e6;
int pri[MAXN+1];
int &pritop=pri[0];
ll ans[MAXN+1];
int pk[MAXN+1];//pk(n)=pk的最小因子p的次方
void sieve(int n=MAXN) {
ans[1]=1;
pk[1]=1;
for(int i=2; i<=n; i++) {
if(!pk[i]) {
pri[++pritop]=i;
ans[i]=i+i-1;
pk[i]=i;
}
for(int j=1; j<=pritop&&i*pri[j]<=n; j++) {
int t=i*pri[j];
if(i%pri[j]) {
pk[t]=pk[pri[j]];
ans[t]=ans[i]*ans[pri[j]];
} else {
pk[t]=pk[i]*pri[j];
if(pk[t]==t) {
//纯p的幂次,没有其他因子,这样算不会漏因子
//t-t/pri[j]就是phi[t]
ans[t]=(t-t/pri[j])+ans[i]*pri[j];
} else {
//积性函数
ans[t]=ans[pk[t]]*(ans[t/pk[t]]);
}
break;
}
}
}
for(int i=1; i<=n; i++)
ans[i]+=ans[i-1]-i;
}
inline void solve() {
sieve();
int T=read();
while(T--) {
int n=read();
write(ans[n]);
putchar('\n');
}
}
int main() {
#ifdef Yinku
freopen("Yinku.in","r",stdin);
#endif // Yinku
solve();
return 0;
}
其他尝试?
现在把g放回去。
\(\sum\limits_{g=1}^{n}\sum\limits_{i=1}^{\lfloor\frac{n}{g}\rfloor}g*{\varphi(i)}, (\varphi(1)=0)\)
这个不就是相当于把每个 \(i*g \leq n\) 的加起来吗?所以当然可以交换求和顺序!
\(\sum\limits_{i=1}^{n}\sum\limits_{g=1}^{\lfloor\frac{n}{i}\rfloor}g*{\varphi(i)}, (\varphi(1)=0)\)
前面是一个干净的前缀和,后面那个式子是nlogn的!
也就是预处理:
\(ans(n)=\sum\limits_{g=1}^{\lfloor\frac{n}{i}\rfloor}g*{\varphi(i)}, (\varphi(1)=0)\)
51nod - 1188 - 最大公约数之和 V2 - 数论的更多相关文章
- 51nod 1188 最大公约数之和 V2
第二个\( O(T\sqrt(n)) \)复杂度T了..T了..T了...天地良心,这能差多少?! 于是跑去现算(. \[ \sum_{i=1}^{n-1}\sum_{j=i+1}^{n}gcd(i, ...
- 51 nod 1188 最大公约数之和 V2
1188 最大公约数之和 V2 题目来源: UVA 基准时间限制:2 秒 空间限制:262144 KB 分值: 160 难度:6级算法题 给出一个数N,输出小于等于N的所有数,两两之间的最大公约数 ...
- 1188 最大公约数之和 V2
1188 最大公约数之和 V2 题目来源: UVA 基准时间限制:2 秒 空间限制:262144 KB 给出一个数N,输出小于等于N的所有数,两两之间的最大公约数之和. 相当于计算这段程 ...
- 51nod 1040:最大公约数之和(数论)
题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1040 给出一个n,求1-n这n个数,同n的最大公约数的和. ...
- 51nod1188 最大公约数之和 V2
考虑每一个数对于答案的贡献.复杂度是O(nlogn)的.因为1/1+1/2+1/3+1/4......是logn级别的 //gcd(i,j)=2=>gcd(i/2,j/2)=1=>phi( ...
- 51nod 1040 最大公约数之和(欧拉函数)
1040 最大公约数之和 题目来源: rihkddd 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 给出一个n,求1-n这n个数,同n的最大公约数的和.比如: ...
- 51nod 1237 最大公约数之和 V3(杜教筛)
[题目链接] https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1237 [题目大意] 求[1,n][1,n]最大公约数之和 ...
- 51nod 1040 最大公约数之和 欧拉函数
1040 最大公约数之和 题目连接: https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1040 Description 给 ...
- 51NOD 1237 最大公约数之和 V3 [杜教筛]
1237 最大公约数之和 V3 题意:求\(\sum_{i=1}^n\sum_{j=1}^n(i,j)\) 令\(A(n)=\sum_{i=1}^n(n,i) = \sum_{d\mid n}d \c ...
随机推荐
- PHP date()获取系统时间不对
使用date_default_timezone_set(”)方法; <?php error_reporting(0); date_default_timezone_set('PRC'); hea ...
- compute the su procedure time with python
#!/usr/bin/python2.6 import re,datetime file_name='sim.log' file=open(file_name,'r') acnum=[];time_r ...
- 【Web探索之旅】第三部分第一课:server
wx_fmt=jpeg" alt="0? wx_fmt=jpeg" style="height:auto"> 内容简单介绍 .第三部分第一课:s ...
- 监控hadoop任务结果shell脚本
需求:每日hadoop结果文件中,找出数据不完整的日期和没有跑出数据的日期,重新进行跑hadoop任务 分析:在result/目录生成的文件中数据有2个特点 第一:日期有,但是数据不完整 第二:日期对 ...
- ThreadPoolTaskExecutor
我们在开发过程中经常要用到线程池,线程池应该统一管理起来,而不是随用随建.ThreadPoolTaskExecutor——将线程池交给spring管理 1. ThreadPoolTaskExecuto ...
- windows下使用ofstream默认输出内存数据到文件中时,会自动将0A换成0A0D
0A即\n,而0D是\r,windows下换行是\n\r,因此会自动转换. 但是,这样会带来很大的问题,导致由内存写入文件中的数据和内存中不一样,还不知道是什么原因造成的. 特别是将从网络接收来的pn ...
- iOS 设备获取唯一标识符汇总
在2013年3月21日苹果已经通知开发者,从2013年5月1日起,访问UIDID的应用将不再能通过审核,替代的方案是开发者应该使用“在iOS 6中介绍的Vendor或Advertising标示符”. ...
- BZOJ2120 数颜色 —— 待修改莫队
题目链接:https://vjudge.net/problem/HYSBZ-2120 2120: 数颜色 Time Limit: 6 Sec Memory Limit: 259 MBSubmit: ...
- 基于BASYS2的VHDL程序与烧写——按键消抖程序
请尊重作者版权,转载请注明源地址http://www.cnblogs.com/connorzx/p/3548364.html 按键在按下的过程中通常会产生一段时间的抖动,为了消除这种抖动,一般采取两种 ...
- Partition算法及Partition算法用于快速排序
JavaScript简单方便,所以用JavaScript实现,可以在Chrome控制台下观察运行结果.主要实现Partition算法,比如输入为 var array = [4, 2, 1, 3, ...