博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【题解】最大公约数之和 V3 51nod 1237 杜教筛
阅读量:6414 次
发布时间:2019-06-23

本文共 3618 字,大约阅读时间需要 12 分钟。

题目传送门 http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1237

数学题真是做的又爽又痛苦,爽在于只要推出来公式基本上就是AC,痛苦就在于推公式。。。

题意很简单,求

$\Large\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}gcd(i,j)$

其中$n\le 10^{10}$

这个题有很多做法,除了普及组的$O(n^2\log n)$做法,还有用莫比乌斯反演+分块优化的$O(n)$做法

然而因为这个题两个维度的限制是相等的,都是$n$,所以可以用杜教筛做到$O(n^{\frac{2}{3}})$

然后推一波公式

$\Large\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}gcd(i,j)$

按照套路,可以枚举最大公因数$g$,于是有

$\Large\sum\limits_{g=1}^{n}\sum\limits_{g=gcd(i,j)}g$

继续变形

$\Large\sum\limits_{g=1}^{n}g\cdot(\sum\limits_{g=gcd(i,j)}1)$

$\Large\sum\limits_{g=1}^{n}g\cdot(\sum\limits_{1=gcd(i,j)}^{i\le\lfloor\frac{n}{g}\rfloor,j\le\lfloor\frac{n}{g}\rfloor}1)$

到这里,我们就可以用莫比乌斯反演的套路做到$O(n)$的复杂度了,但是我们换种形式继续推式子

我们先关注这一部分的变形,暂时不管前面的那一部分

$\Large\sum\limits_{1=gcd(i,j)}^{i\le\lfloor\frac{n}{g}\rfloor,j\le\lfloor\frac{n}{g}\rfloor}1$

展开,得到

$\Large\sum\limits_{i=1}^{\lfloor\frac{n}{g}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{n}{g}\rfloor}[gcd(i,j)=1]\cdot 1$

其中$[gcd(i,j)=1]$的意思是,当$gcd(i,j)=1$的时候这个东西的值为$1$,否则为$0$

然后用$\varphi()$函数进行化简,于是式子就变成了

$\Large 2\cdot(\sum\limits_{i=1}^{\lfloor\frac{n}{g}\rfloor}\varphi(i))-1$

注意到中间的一部分是$\varphi()$函数的前缀和,于是我们可以用杜教筛算

为了方便,设函数

$\Large S(n)=\sum\limits_{i=1}^{n}\varphi(i)$

然后再看一眼总的式子

$\Large\sum\limits_{g=1}^{n}g\cdot(2\cdot S(\lfloor\frac{n}{g}\rfloor)-1)$

于是$\lfloor\frac{n}{g}\rfloor$是整除,可以用分块优化,这样的话,除去杜教筛求$S()$的部分,复杂度是$O(n^{\frac{1}{2}})$

因为杜教筛有记忆化,复杂度和分块优化的部分是分离的,所以总复杂度是

$\Large O(n^{\frac{1}{2}}+n^{\frac{2}{3}})=O(n^{\frac{2}{3}})$

单点时限$5s$,我杜教筛记忆化用的$map$,没有自己手写$hash$,于是复杂度就多了$O(\log n)$,但是仍然每个点跑到了$1s$以内,还是挺不错的

上代码:

1 #include 
2 #include
3 #include
4 #include
5 6 using namespace std; 7 typedef long long ll; 8 const int MOD = 1e9+7; 9 const int LIMIT = 4641589;10 11 bool vis[LIMIT] = {
0};12 ll prime[LIMIT], pidx = 0, phi[LIMIT] = {
0}, pfphi[LIMIT] = {
0};13 void prelude_phi() { // 线性筛预处理一部分前缀和14 phi[1] = 1;15 for( ll i = 2; i < LIMIT; ++i ) {16 if( !vis[i] ) {17 prime[pidx++] = i;18 phi[i] = i-1;19 }20 for( int j = 0; j < pidx; ++j ) {21 ll k = i * prime[j];22 if( k >= LIMIT ) break;23 vis[k] = true;24 if( i % prime[j] ) phi[k] = phi[i] * phi[prime[j]] % MOD;25 else {26 phi[k] = phi[i] * prime[j] % MOD;27 break;28 }29 }30 }31 for( int i = 1; i < LIMIT; ++i )32 pfphi[i] = (pfphi[i-1] + phi[i]) % MOD;33 }34 35 ll inv2;36 ll pow_mod( ll a, ll b ) {37 if( !b ) return 1;38 ll rtn = pow_mod(a,b>>1);39 rtn = rtn * rtn % MOD;40 if( b&1 ) rtn = rtn * a % MOD;41 return rtn;42 }43 ll inv( ll x ) {44 return pow_mod(x,MOD-2);45 }46 47 map
mp; // 记忆化用48 ll S( ll n ) { // 杜教筛求前缀和49 if( n < LIMIT ) return pfphi[n];50 if( mp.count(n) ) return mp[n];51 ll ans = (n % MOD) * ((n+1) % MOD) % MOD * inv2 % MOD;52 for( ll i = 2, j; i <= n; i = j+1 ) {53 j = n/(n/i);54 ans = (ans - S(n/i) * ((j-i+1) % MOD) % MOD + MOD) % MOD;55 }56 mp[n] = ans;57 return ans;58 }59 60 ll n;61 62 void solve() {63 ll ans = 0;64 for( ll i = 1, j; i <= n; i = j+1 ) {65 j = n/(n/i); // 分块优化66 ans = (ans + (((i+j) % MOD) * ((j-i+1) % MOD) % MOD * inv2 % MOD) * ((2 * S(n/i) - 1) % MOD) % MOD ) % MOD;67 }68 printf( "%lld\n", ans );69 }70 71 int main() {72 prelude_phi();73 inv2 = inv(2);74 scanf( "%lld", &n );75 solve();76 return 0;77 }

 

转载于:https://www.cnblogs.com/mlystdcall/p/6633434.html

你可能感兴趣的文章
Linux TTY、PTS、PTY详解
查看>>
java泛型中T、E、K、V、?等含义
查看>>
UITableView中使用reloadRowsAtIndexPaths会出现闪退的解决办法
查看>>
Banner无限轮播图
查看>>
Java 静态代理、Java动态代理、CGLIB动态代理
查看>>
zabbix监控memcached模板
查看>>
JavaScript中的对象
查看>>
ELK中的redis的问题记录
查看>>
zabbix low level discovery example use python(web_site_url)
查看>>
分布式服务Dubbo+Zookeeper安全认证
查看>>
我的友情链接
查看>>
request.getRequestURI() 、request.getRequestURL()
查看>>
二叉查找树--查找、删除、插入(Java实现)
查看>>
简单的UDP多线程模型
查看>>
Unity曲线编辑器和bezier曲线插值
查看>>
android中数据存储的ContentProvider的使用方法
查看>>
网络系统管理与维护2488
查看>>
裸机telnet处理过程记录
查看>>
Nginx源码安装及调优
查看>>
EasyUi subgrid 三级列表实现
查看>>