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}\)的复杂度,因为第二个根号是求欧拉函数的复杂度,所以实际的复杂度没有这么高

代码:

#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll;
ll phi(ll x)
{
ll ans=1;
for(ll i=2;i*i<=x;++i)
{
if(x%i==0)
{
ans*=(i-1);
x/=i;
}
while(x%i==0)
{
ans*=i;
x/=i;
}
}
if(x!=1)
ans*=(x-1);
return ans;
}
int main()
{
ios::sync_with_stdio(false);
ll n;
cin>>n;
ll ans=0;
ll i;
for(i=1;i*i<=n;++i)
if(n%i==0)
ans+=i*phi(n/i)+(n/i)*phi(i);
if(i*i==n) ans-=i*phi(i);
cout<<ans;
return 0;
}

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)
\]

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

代码:

#include<cstdio>
#include<iostream>
using namespace std;
const int N=100000+100;
int phi[N],phi_sum[N];
void getphi()
{
for(int i=1;i<N;++i)
phi[i]=i;
phi[1]=1;
for(int i=2;i<N;++i)
if(phi[i]==i)
for(int j=i;j<=N;j+=i)
phi[j]=phi[j]/i*(i-1);
for(int i=1;i<N;++i)
phi_sum[i]=phi_sum[i-1]+phi[i];
}
int n;
int main()
{
getphi();
while(1)
{
scanf("%d",&n);
if(!n) break;
long long ans=0;
for(int i=1;i<=n;++i)
ans+=phi_sum[n/i]*i;
cout<<ans<<endl;
}
return 0;
}

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
\]

代码:

#include<cstdio>
#include<iostream>
using namespace std;
const int N=100000+100;
int phi[N],phi_sum[N];
void getphi()
{
for(int i=1;i<N;++i)
phi[i]=i;
phi[1]=1;
for(int i=2;i<N;++i)
if(phi[i]==i)
for(int j=i;j<=N;j+=i)
phi[j]=phi[j]/i*(i-1);
for(int i=1;i<N;++i)
phi_sum[i]=phi_sum[i-1]+phi[i];
}
int n;
int main()
{
getphi();
while(1)
{
scanf("%d",&n);
if(!n) break;
long long ans=0;
for(int i=1;i<=n;++i)
ans+=(phi_sum[n/i]-1)*i;
cout<<ans<<endl;
}
return 0;
}

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
\]

代码:

#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll;
const int N=100000+100;
ll ans,phi[N],phi_sum[N],n;
void getphi()
{
for(int i=1;i<N;++i)
phi[i]=i;
phi[1]=1;
for(int i=2;i<N;++i)
if(phi[i]==i)
for(int j=i;j<=N;j+=i)
phi[j]=phi[j]/i*(i-1);
for(int i=1;i<N;++i)
phi_sum[i]=phi_sum[i-1]+phi[i];
}
int main()
{
cin>>n;
getphi();
for(int i=1;i<=n;++i)
ans+=(phi_sum[n/i]*2-1)*i;
cout<<ans;
return 0;
}

关于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. 使用Python画玫瑰花

    ''' Created on Nov 18, 2017 @author: QiZhao ''' import turtle # 设置初始位置 turtle.penup() turtle.left(90 ...

  2. Dynamics 365 启用跟踪及读取跟踪文件工具

    微软动态CRM专家罗勇 ,回复315或者20190313可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!我的网站是 www.luoyong.me . 当根据错误提示排查问 ...

  3. SpringBoot 集成Apache Kafak 消息队列

    Kafka is a distributed,partitioned,replicated commit logservice.它提供了类似于JMS的特性,但是在实现上完全不同,此外它并不是JMS规范 ...

  4. Java中的Iterable与Iterator详解

    在Java中,我们可以对List集合进行如下几种方式的遍历: List<Integer> list = new ArrayList<>(); list.add(5); list ...

  5. EF 底层封装方法(供参考)

    闲暇之余,整理了一下EF底层的一些基础方法,供查看,只有接口,具体实现需要你们自己写了. 建议:接口的实现定义为虚方法,当父类的方法不满住子类需求时,可以重写此方法 此接口都为公用方法,基本上满足小系 ...

  6. svn + nginx unit + python3自动化发布web服务方法

    本周将python web服务管理更换成nginx unit以后发现接口性能有了明显的提升,访问速度快了不少.不过有个很大的问题就是使用svn自动化发布以后,服务并没有刷新使用新的代码运行,而又不懂得 ...

  7. 【转】不需要 Root,也能用上强大的 Xposed 框架:VirtualXposed

    如果你喜欢折腾 Android 设备,那么你应该对 Xposed 的大名有所耳闻. 这个第三方框架,让许多 Android 玩家都爱不释手.通过对系统框架的「偷天换日」,它可以修改系统与应用的各种数据 ...

  8. redis对sorted_set进行的相关操作

    redis对sorted_set(有序集合)类型操作的相关命令以及如何在python使用这些命令 redis对sorted_set(有序集合)类型操作的命令: 命令 语法 概述 返回值 Redis Z ...

  9. UML在代码中的展现

    依赖:一个类使用了另外一个类,这种关系是临时的.脆弱的. 如人需要过河,需要船,这时人.过河(船)  中船被当做参数传入,船的实现变化会影响过河方法.     聚合:体现是整体与部分.has-a的关系 ...

  10. mysql中将多行数据合并成一行数据

    .1GROUP_CONCAT()中的值为你要合并的数据的字段名; SEPARATOR 函数是用来分隔这些要合并的数据的: ' '中是你要用哪个符号来分隔: 2.必须要用GROUP BY 语句来进行分组 ...