gcd套路变换

GCD

https://www.luogu.org/problem/P2568

给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的数对(x,y)有多少对.

$ 1<=N<=10^7$

答案是n*n矩阵中每两个数之间gcd==1的数对个数

考虑把\(n\times n\)的矩阵分成两部分,即从对角线劈开,设每一部分的答案为ans,则最终答案为$ ans*2 - 对角线上的(即n以内的质数个数)$

这个把矩阵分成两部分的方法很有用,记一下吧

\[ans = \sum_{i = 1}^{n}\sum_{j = 1}^{i} isprime[\gcd(i, j)]
\]

套路变形,枚举d = gcd(i, j),

则上述式子等价于

\[ans = \sum_{d = 1}^{n}\, isprime[d]\,\sum_{i = 1}^{n}\sum_{j = 1}^{i}[\gcd(i, j) == d]
\]

又因为:

\[i = 2d, 3d, 4d....kd。 j = 2d, 3d....sd
\]

所以有

\[\sum_{i = 1}^{n}\sum_{j = 1}^{I}[gcd(i, j) == d] = \,\,\sum_{i = 1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{i} [\gcd(i, j) == 1]
\]

所以如下套路:

\[ans = \sum_{d = 1}^{n}isprime[d]\sum_{i = 1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{i} [\gcd(i, j) == 1]
\]

后面的显然就是\(\varphi(i)\) , 然后算上中间的\(\sum\), 就是前\(\lfloor\frac{n}{d}\rfloor\) 个数的$ \varphi $和,求一个前缀和即可

\[ans = \sum_{d=1}^{n}isprime[d]*s[\frac{n}{i}]
\]

对于d,我们可以直接枚举为质数的情况,因为这题要求的是素数对数,其他不是素数的d对答案都是没有贡献的,所以考虑d为素数的情况,\(isprime[d] == 1\), 所以一个for累加即可

#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 10000000+9; int n;
long long ans;
int not_prime[N] = {1, 1}, prime[N], tot, phi[N];
long long sum[N]; void L_S() {
phi[1] = 1;
for(int i = 2; i <= n; i++) {
if(!not_prime[i]) {
prime[++tot] = i;
phi[i] = i-1;
}
for(int j = 1; j <= tot && i*prime[j] <= n; j++) {
not_prime[i*prime[j]] = 1;
if(i % prime[j] == 0) {
phi[i*prime[j]] = phi[i]*prime[j];
break;
}
phi[i*prime[j]] = phi[i]*(prime[j]-1);
}
}
for(int i = 1; i <= n; i++) sum[i] = (long long)sum[i-1]+phi[i];
} int main() {
scanf("%d", &n);
L_S();
for(int i = 1;i <= tot; i++) ans += sum[n/prime[i]];//prime[i]即为d
printf("%lld", ans*2-tot);
}

注:不求数量,求值也是这样的套路,只不过要乘以d

[SDOi2012]Longge的问题

求 ∑gcd(i, N)(1<=i <=N)

0<N<=2^32

枚举d = gcd(i, n)

原式进行如下变换:

\[\sum_{d=1}^{n} d \sum_{i=1}^{n}[\gcd(i, n) == d]
\]

再次套路

\[\sum_{d=1}^{n} d \sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}[gcd(i, \frac{n}{d}) == 1]
\]

后面的还是上面的那个

\[\sum_{d=1}^{n} d\times \varphi(\lfloor\frac{n}{d}\rfloor)
\]

**我们对于每个d,要求在区间$[1, \lfloor\frac{n}{d}\rfloor ] $ 内有多少i使得gcd(i,n/d)=1,设求出有x个i,那么对答案的贡献就是$ d \times x$ **

这题和上题不一样,不是对于素数求这个式子,所以我们需要枚举n的因数, 所以单个求phi即可。

这种枚举因数的方法可以记一下(个人感觉有点上面分矩阵的思想

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define ll long long ll el_phi(ll n) {
ll m = sqrt(n+0.5);
ll ans = n;
for(ll i = 2; i <= m; i++) if(n%i == 0) {
ans = ans/i*(i-1);
while(n%i == 0) n /= i;
}
if(n > 1) ans = ans/n*(n-1);
return ans;
}
ll n, ans; int main() {
scanf("%lld", &n);
ll m = sqrt(n+0.5);
for(ll i = 1; i <= m; i++) if(n % i == 0) {
ans += i*el_phi(n/i);
if(i*i != n) ans += el_phi(i)*(n/i);//i * i != n时i和n/i都是n的因数
}
printf("%lld", ans);
return 0;
}

[SDOI2008]仪仗队

与第一题双倍经验

https://www.luogu.org/problem/P2158

求$ Σ(1<=i<=n)Σ(1<=j<=i)[gcd(i,j)==1] $

得,原式 = $ Σ(1<=i<=n) φ(i) $

做法: 欧拉线性筛

#include<cstdio>
#include<algorithm>
#include<set>
using namespace std;
const int MAXN = 40000+9; int n,ans;
int phi[MAXN], not_prime[MAXN], prime[MAXN], tot; void L_S() {
phi[1] = 1;
for(int i = 2; i <= n; i++) {
if(!not_prime[i]) {
prime[++tot] = i;
phi[i] = i-1;
}
for(int j = 1; i*prime[j] <= n; j++) {
not_prime[prime[j]*i] = 1;
if(i % prime[j] == 0) {
phi[i*prime[j]] = phi[i]*prime[j];
break;
}
phi[i*prime[j]] = phi[i]*(prime[j]-1);
}
}
} int main() {
scanf("%d",&n);
if(n == 0 || n == 1) {
printf("0");
return 0;
}
n--;
L_S();
for(int i = 1; i <= n; i++) ans += phi[i];
printf("%d",(ans<<1)-1+2);
}

SP5971 LCMSUM - LCM Sum

求$ \sum_{i=1}^{n} ; lcm(i,n)$

$ 1<=T<=300000 , 1 <= n <= 1000000 $

原式进行如下变形:

\[\sum_{i=1}^{n} \frac{i\times n}{\gcd(i, n)}
\]

套路变形,注意:这里是要求求值

\[\sum_{d\mid n} \frac{n}{d}\sum_{i=1}^{n}i\,[\gcd(i, n)==d]
\]

注意这一步,上面是\(i\), 变除法的时候要注意

\[\sum_{d\mid n}\frac{n}{d} \sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}i\times d[\gcd(i, \lfloor\frac{n}{d}\rfloor) == 1]
\]

结合:[1,n]范围内 与n互质的数 的和:(φ(n)∗n)/2,化简得:

\[n\times \sum_{d\mid n} (\varphi(\frac{n}{d})\times \frac{n}{d})/2
\]

即:

\[n\times \sum_{d\mid n} \frac{\varphi(d)\times d}{2}
\]

for(int i = 1; i <= N; i++)
for(int j = i; j <= N; j+=i) //i为j的因数, 所以是'f[j] +='
f[j] += i==1 ? 1 : 1ll*phi[i]*i/2;//i==1时对f的贡献应该是1

gcd套路变换的更多相关文章

  1. 洛谷1072(gcd的运用)

    已知正整数a0,a1,b0,b1,设某未知正整数x满足: 1. x 和 a0 的最大公约数是 a1​: 2. x 和 b0​ 的最小公倍数是b1. Hankson 的“逆问题”就是求出满足条件的正整数 ...

  2. 「BZOJ 3529」「SDOI 2014」数表「莫比乌斯反演」

    题意 有一张 \(n\times m\) 的数表,其第\(i\)行第\(j\)列的数值为能同时整除\(i\)和\(j\)的所有自然数之和. \(T\)组数据,询问对于给定的 \(n,m,a\) , 计 ...

  3. [BZOJ 4921][Lydsy1706月赛]互质序列

    传送门 因为区间 gcd 的变换不会超过 log 个,所以我们可以暴力枚举区间起点,复杂度是 n*logn 的 #include <bits/stdc++.h> using namespa ...

  4. 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/常用套路【入门】

    原文链接https://www.cnblogs.com/zhouzhendong/p/Fast-Fourier-Transform.html 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/ ...

  5. 莫比乌斯反演套路一--令t=pd--BZOJ2820: YY的GCD

    t<=10000组询问:有多少x,y,满足$x\epsilon [1,n],y\epsilon [1,m],(x,y)为质数$.n,m<=1e7. 首先式子列出来,f(i)--1<= ...

  6. 【BZOJ2820】YY的GCD

    [BZOJ2820]YY的GCD Description 神犇YY虐完数论后给傻×kAc出了一题 给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的( ...

  7. [学习笔记&教程] 信号, 集合, 多项式, 以及各种卷积性变换 (FFT,NTT,FWT,FMT)

    目录 信号, 集合, 多项式, 以及卷积性变换 卷积 卷积性变换 傅里叶变换与信号 引入: 信号分析 变换的基础: 复数 傅里叶变换 离散傅里叶变换 FFT 与多项式 \(n\) 次单位复根 消去引理 ...

  8. ReactiveCocoa 中 RACSignal 所有变换操作底层实现分析(上)

    前言 在上篇文章中,详细分析了RACSignal是创建和订阅的详细过程.看到底层源码实现后,就能发现,ReactiveCocoa这个FRP的库,实现响应式(RP)是用Block闭包来实现的,而并不是用 ...

  9. [洛谷2257]YY的GCD 题解

    整理题目转化为数学语言 题目要我们求: \[\sum_{i=1}^n\sum_{i=1}^m[gcd(i,j)=p]\] 其中 \[p\in\text{质数集合}\] 这样表示显然不是很好,所以我们需 ...

随机推荐

  1. 【译】浅谈SOLID原则

    SOLID原则是一种编码的标准,为了避免不良设计,所有的软件开发人员都应该清楚这些原则.SOLID原则是由Robert C Martin推广并被广泛引用于面向对象编程中.正确使用这些规范将提升你的代码 ...

  2. Python高级特性——迭代(Iteration)

    1.给定一个集合list或者tuple,可以通过for …… in ……的语法来实现循环遍历,这个循环我们就叫做迭代 迭代list: >>> m = ['haha','hehe',' ...

  3. Redis 实现美团的外卖派单系统“附近的人”筛选实战原理分析

    针对“附近的人”这一位置服务领域的应用场景,常见的可使用PG.MySQL和MongoDB等多种DB的空间索引进行实现.而Redis另辟蹊径,结合其有序队列zset以及geohash编码,实现了空间搜索 ...

  4. Ubuntu Server 上使用Docker Compose 部署Nexus(图文教程)

    场景 Docker-Compose简介与Ubuntu Server 上安装Compose: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/deta ...

  5. 字段明明存在,用Web API使用该字段进行查询报错?

    我是微软Dynamics 365 & Power Platform方面的工程师罗勇,也是2015年7月到2018年6月连续三年Dynamics CRM/Business Solutions方面 ...

  6. LeetCode刷题191126

    博主渣渣一枚,刷刷leetcode给自己瞅瞅,大神们由更好方法还望不吝赐教.题目及解法来自于力扣(LeetCode),传送门. 今天状态不好,划水第二天. 算法: 题号:20 给定一个只包括 '(', ...

  7. EasyExcel示例(阿里巴巴)基于Maven

    首先感谢阿里巴巴提供了easyexcel工具类,github地址:https://github.com/alibaba/easyexcel 注意!!这里只是一个简单的示例,VC大法即可使用,对于复杂的 ...

  8. 快速排序 Vs. 归并排序 Vs. 堆排序——谁才是最强的排序算法

    知乎上有一个问题是这样的: 堆排序是渐进最优的比较排序算法,达到了O(nlgn)这一下界,而快排有一定的可能性会产生最坏划分,时间复杂度可能为O(n^2),那为什么快排在实际使用中通常优于堆排序? 昨 ...

  9. docker alphine 设置系统日期

    设置时区为上海 RUN apk add tzdata && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && ...

  10. Java+TestNG+Maven+Excel+IDEA接口自动化入门(一)环境配置

    前置: 1.本机环境安装了maven并配置环境变量 2.本机环境安装了IDEA软件 3.本机环境安装了Java jdk 8版本 4.有一定java和maven基础 因为以上网上例子很多,就不再重复赘述 ...