T1:

bzoj2705

题目描述:

给定一个n求\(\sum\limits_{i=1}^ngcd(i,n)\)

因为n太大,所以O(n)的做法肯定不行,然后就去想根号的方法。

\[\sum\limits_{i=1}^{n}gcd(i,n)
\]

\[=\sum\limits_{k|n}k*\sum\limits_{i=1}^n[gcd(i,n)==k]
\]

\[=\sum\limits_{k|n}k*\sum\limits_{i=1}^n[gcd(\frac{i}{k},\frac{n}{k})==1]
\]

\[=\sum\limits_{k|n}k*\sum_{i=1}^{\frac{n}{k}}[gcd(i,\frac{n}{k})==1]
\]

\[=\sum_{k|n}{k*φ(\frac{n}{k})}
\]

然后i从1到\(\sqrt{n}\)去枚举n的因数,然后将i*φ(n/i)与n/i与φ(i)全部计入答案,就可以做到\(\sqrt{n}*\sqrt{n}\)的复杂度,因为第二个根号是求欧拉函数的复杂度,所以实际的复杂度没有这么高

代码:

  1. #include<cstdio>
  2. #include<iostream>
  3. using namespace std;
  4. typedef long long ll;
  5. ll phi(ll x)
  6. {
  7. ll ans=1;
  8. for(ll i=2;i*i<=x;++i)
  9. {
  10. if(x%i==0)
  11. {
  12. ans*=(i-1);
  13. x/=i;
  14. }
  15. while(x%i==0)
  16. {
  17. ans*=i;
  18. x/=i;
  19. }
  20. }
  21. if(x!=1)
  22. ans*=(x-1);
  23. return ans;
  24. }
  25. int main()
  26. {
  27. ios::sync_with_stdio(false);
  28. ll n;
  29. cin>>n;
  30. ll ans=0;
  31. ll i;
  32. for(i=1;i*i<=n;++i)
  33. if(n%i==0)
  34. ans+=i*phi(n/i)+(n/i)*phi(i);
  35. if(i*i==n) ans-=i*phi(i);
  36. cout<<ans;
  37. return 0;
  38. }

T2:

exbzoj2705:

没有评测,

题目描述:

给定一个整数n(1<=n<=100000),你需要求出\(\sum\limits_{i=1}^n\sum\limits_{j=1}^igcd(i,j)\)

暴力做法:将上个题中的n循环起来,最后记录每个循环所求的和。明显TLE

正解:

\[\sum\limits_{i=1}^n\sum\limits_{j=1}^igcd(i,j)
\]

枚举因数k

\[\sum\limits_{k=1}^nk*\sum\limits_{i=1}^n\sum\limits_{j=1}^i[gcd(i,j)==k]
\]

考虑所有最大公因数为k的情况,设\(i=ak,j=bk(a>=b)\)若要i与j做大公约数为k,则必须满足gcd(a,b)=1,满足此条件的所有情况数为φ(b),然后考虑b的取值范围,因为必须满足b*k<=n,所以\(b<=[\frac{n}{k}]\)。所以答案为

\[\sum\limits_{k=1}^nk*\sum\limits_{i=1}^{\frac{n}{k}}φ(i)
\]

所以线性求出欧拉函数,并求出前缀和即可。

代码:

  1. #include<cstdio>
  2. #include<iostream>
  3. using namespace std;
  4. const int N=100000+100;
  5. int phi[N],phi_sum[N];
  6. void getphi()
  7. {
  8. for(int i=1;i<N;++i)
  9. phi[i]=i;
  10. phi[1]=1;
  11. for(int i=2;i<N;++i)
  12. if(phi[i]==i)
  13. for(int j=i;j<=N;j+=i)
  14. phi[j]=phi[j]/i*(i-1);
  15. for(int i=1;i<N;++i)
  16. phi_sum[i]=phi_sum[i-1]+phi[i];
  17. }
  18. int n;
  19. int main()
  20. {
  21. getphi();
  22. while(1)
  23. {
  24. scanf("%d",&n);
  25. if(!n) break;
  26. long long ans=0;
  27. for(int i=1;i<=n;++i)
  28. ans+=phi_sum[n/i]*i;
  29. cout<<ans<<endl;
  30. }
  31. return 0;
  32. }

T3:

uva11417

别问我为什么是luogu

题目描述:

给定一个整数n(1<=n<=100000),求\(\sum\limits_{i=1}^{n-1}\sum\limits_{j=i+1}^ngcd(i,j)\)

解法:

\[\sum\limits_{i=1}^{n-1}\sum\limits_{j=i+1}^ngcd(i,j)
\]

枚举因数k

\[\sum\limits_{k=1}^nk*\sum\limits_{i=1}^{n-1}\sum\limits_{j=i+1}^n[gcd(i,j)==k]
\]

考虑所有最大公因数为k的情况,设\(i=ak,j=bk(b>a)\)若要i与j做大公约数为k,则必须满足gcd(a,b)=1,满足此条件的所有情况数为φ(b),然后考虑b的取值范围,因为必须满足b*k<=n,所以\(b<=[\frac{n}{k}]\)。所以答案为

\[\sum\limits_{k=1}^nk*\sum\limits_{i=1}^{\frac{n}{k}}φ(i)
\]

所以线性求出欧拉函数,并求出前缀和即可。

为什么和上面一样

但是因为i和j都不能为0并且j>i即b>a,所以b不能为1,所以要在最后减去φ(1)的情况,也就相当于把里面的i从2开始枚举。

所以最终答案为

\[\sum\limits_{k=1}^nk*\sum\limits_{i=1}^{\frac{n}{k}}φ(i)-1
\]

代码:

  1. #include<cstdio>
  2. #include<iostream>
  3. using namespace std;
  4. const int N=100000+100;
  5. int phi[N],phi_sum[N];
  6. void getphi()
  7. {
  8. for(int i=1;i<N;++i)
  9. phi[i]=i;
  10. phi[1]=1;
  11. for(int i=2;i<N;++i)
  12. if(phi[i]==i)
  13. for(int j=i;j<=N;j+=i)
  14. phi[j]=phi[j]/i*(i-1);
  15. for(int i=1;i<N;++i)
  16. phi_sum[i]=phi_sum[i-1]+phi[i];
  17. }
  18. int n;
  19. int main()
  20. {
  21. getphi();
  22. while(1)
  23. {
  24. scanf("%d",&n);
  25. if(!n) break;
  26. long long ans=0;
  27. for(int i=1;i<=n;++i)
  28. ans+=(phi_sum[n/i]-1)*i;
  29. cout<<ans<<endl;
  30. }
  31. return 0;
  32. }

T4:

luogu2398

题目描述:

给定一个n(1<=n<=100000),求\(\sum\limits_{i=1}^n\sum\limits_{j=1}^ngcd(i,j)\)

解法:

发现这个题数上面两个题的综合,所以,嘿嘿,将上面的两个题答案加起来即可,所以最终答案为

\[\sum\limits_{k=1}^n2*k*\sum\limits_{i=1}^{\frac{n}{k}}φ(i)-1
\]

代码:

  1. #include<cstdio>
  2. #include<iostream>
  3. using namespace std;
  4. typedef long long ll;
  5. const int N=100000+100;
  6. ll ans,phi[N],phi_sum[N],n;
  7. void getphi()
  8. {
  9. for(int i=1;i<N;++i)
  10. phi[i]=i;
  11. phi[1]=1;
  12. for(int i=2;i<N;++i)
  13. if(phi[i]==i)
  14. for(int j=i;j<=N;j+=i)
  15. phi[j]=phi[j]/i*(i-1);
  16. for(int i=1;i<N;++i)
  17. phi_sum[i]=phi_sum[i-1]+phi[i];
  18. }
  19. int main()
  20. {
  21. cin>>n;
  22. getphi();
  23. for(int i=1;i<=n;++i)
  24. ans+=(phi_sum[n/i]*2-1)*i;
  25. cout<<ans;
  26. return 0;
  27. }

关于gcd的四道题的更多相关文章

  1. DDCTF2019 的四道题wp

    MIsc:流量分析 这道题,在比赛的时候就差个key了,但是没想到要改高度,后来群里师傅说了下,就再试试, 导出来改高度. 导出来,把 把%5c(4)前面的hex删掉,改成png,就直接拿去那个img ...

  2. lintcode中等题目的四道题

    第一题: 第一句先创建了一个解决问题的类, 第二句声明了一个公共接口的整形链表里面有N个整形数, 第三句给链表动态初始化, 第四步判断链表里的数有没有,如果N<=0则返回结果0,否则执行Prin ...

  3. 深入GCD(四):使用串行队列实现简单的预加载

    其主要思路是使用gcd创建串行队列,然后在此队列中先后执行两个任务:1.预加载一个viewController 2.将这个viewController推入代码如下:@implementation DW ...

  4. lintcode 四道题

    我们考虑对每个字符进行两边扩展,寻找回文串,并记录长度.有两种情况,一种是bab,从a向两边扩展,一种abba,从bb中间向两边扩展. dp[i][j] 表示子串s[i-j]是否是回文 初始化:dp[ ...

  5. google Kickstart Round F 2017 四道题题解

    Problem A. Kicksort 题意抽象一下为: 对于一个每次都从数列正中间取划分数的快速排序,给定一个1-n的排列,问快排的复杂度对于这个排列是否会退化为最坏复杂度. 数据范围: 测试组数1 ...

  6. GCD 学习(四) dispatch_group

    如果想在dispatch_queue中所有的任务执行完成后在做某种操作,在串行队列中,可以把该操作放到最后一个任务执行完成后继续,但是在并行队列中怎么做呢.这就有dispatch_group 成组操作 ...

  7. GCD 扫盲篇

    GCD有四个概念:串行队列.并行队列.同步.异步四者. 如下简介: 这里不仅给出了不确定性,而且也给出了确定性.对于初学者而言,有时候因为那些不确定的东西所造成的疑问会像没有闸却在疾驰的汽车一样让人惊 ...

  8. NOIP2012普及组 (四年后的)解题报告 -SilverN

    本章施工仍未完成 现在的时间是3.17 0:28,我困得要死 本来今天(昨天?)晚上的计划是把整个四道题的题解写出来,但是到现在还没写完T4的高效算法,简直悲伤. 尝试了用floyd写T4,终于大功告 ...

  9. ACM第四次积分赛

    虽然因为第一题给的数据有问题,没能四道题都做出来,但是这次第四名,进步很大,继续努力! SAU-ACM总比赛成绩       姓名     账号  上学期成绩 第一次成绩 第二次成绩 第三次成绩 第四 ...

随机推荐

  1. SAP MM 公司间STO里交货单PGI之后自动触发内向交货单功能的实现

    SAP MM 公司间STO里交货单PGI之后自动触发内向交货单功能的实现 笔者所在的项目上的公司间STO的流程里,发货公司在做PGI之后系统自动触发收货公司的内向交货单.这个功能是通过交货单的Outp ...

  2. 一些android开发实用性网站记录

    android开发一些有用的网站有很多,可以方便我们开发,记录一下哈. 1.Android源代码在线阅读:https://www.androidos.net.cn/sourcecode 2.在线Jso ...

  3. WPF:浅析Dispatcher

    本人文笔差.还是直接上代码吧.(本文假设你对WPF中的Dispatcher有一定的了解) 你觉得下面的代码可以正常执行吗? private void Button_Click(object sende ...

  4. 从零学习Fluter(九):正式使用flutter进入商业开发

    一下为下个app 功能模块简要划分 接口文档需要说明 公告接口 messageTitle -- 消息内容 红包墙接口 使用说明 地理位置定位 shareGetMoney - 分享活动金额 lookCo ...

  5. [Python] wxPython 高防Windows10记事本 (end...)

    1.开始 接触Python 也有一段时间了,o.o ,断断续续加起来没几天. 一般新学习一门新语言,除了必先输出一个 Hello World 外,都会以模拟 Windows 记事本来写一个结合自己想法 ...

  6. Jenkins实现简单的CI功能

    步骤一:安装JDK.Tomcat,小儿科的东西不在此详细描述 步骤二:下载安装Jenkins下载链接:https://jenkins.io/download/ 步骤三:将下载的jenkins.war部 ...

  7. c#面试题汇总(1)

    c#面试题汇总 From: https://www.cnblogs.com/suzhiyong1988/p/5069385.html   下面的参考解答只是帮助大家理解,不用背,面试题.笔试题千变万化 ...

  8. WIN10REALTEL高清音频管理器如何调音?调音无效怎么办?

    从win7升级到win10,发现realtel高清音频管理器不能调节高级音响效果了,即使设置也没用. 经过研究后发现是驱动 问题,不是驱动 没有安装,而是可能 没有安装完整,于是下载了驱动精灵,重新安 ...

  9. 父页面内获取获取iframe内的变量或者是获取iframe内的值

    前提:页面不可跨域访问,必须同一域名下,否则返回值为空 父页面 <!DOCTYPE html> <html lang="en"> <head> ...

  10. yaml的用法

    yaml是用来读配置文件的. 一般用yaml或者yml结尾创建文件,格式:key: value.然后在用的时候,像打开文件一样读,返回数据可直接转为字典 使用的时候必须先安装模块并导入.安装:pip ...