gcd

拓展欧几里得算法

僤鯓⒐⒋嵵緔 提交于 2020-03-25 02:53:02
拓展欧几里得算法解二元一次不定方程:a*x+b*y=m; 因为:gcd(a,b)| a , gcd(a,b)| b ; 所以:gcd(a,b)| a*x , gcd(a,b) | b*y ==> gcd(a,b)|(a*x+b*y) ==>gcd(a,b)|m ; 所以要求a*x+b*y=m,可以先求a*x+b*y=gcd(a,b). 对于:a*x+b*y=gcd(a,b) 1.当b==0时,gcd(a,b)=a,此时x=1,y=0; 2.先求出 a*x+b*y=gcd(a,b) 的一组解。 因为 a*x1+b*y1=gcd(a,b) b*x2+a%by2=gcd(b,a%b) 且 gcd(a,b)=gcd(b,a%b); 所以有a*x1+b*y1=b*x2+(a-(a/b)*b)*y2 从而得x1=y2,y1=x2-(a/b)*y2 然后执行程序段: void expgcd(int a,int b,int &x,int &y) { if(b==0) { x=1; y=0; return ; } expgcd(b,a%b,x,y); int t=x; x=y; y=t-(a/b)*y; } 得出一组解x0,y0; 又因为此时的解并非是原不定方程a*x+b*y=m的解并且gcd(a,b)|m 所以的原不定方程的一组解 x1=x0*(m/gcd(a,b)),y1=y0*(m/gcd(a

iOS多线程开发之GCD(死锁篇)

霸气de小男生 提交于 2020-03-22 06:04:02
上篇和中篇讲解了什么是GCD,如何使用GCD,这篇文章将讲解使用GCD中将遇到的死锁问题。有兴趣的朋友可以回顾《 iOS多线程开发之GCD(上篇) 》和《 iOS多线程开发之GCD(中篇) 》。 言归正传,我们首先来回顾下死锁,所谓死锁: 是指两个或两个以上的进程(线程)在执行过程中,因争夺资源(如数据源,内存等,变量不是资源)而造成的一种互相等待的现象,若无外部处理作用,它们都将无限等待下去。   死锁形成的原因: 系统资源不足 进程(线程)推进的顺序不恰当; 资源分配不当   死锁形成的条件: 互斥条件: 所谓互斥就是进程在某一时间内独占资源。 请求与保持条件: 一个进程因请求资源而阻塞时,对已获得的资源保持不放。 不剥夺条件: 进程已获得资源,在末使用完之前,不能强行剥夺。 循环等待条件: 若干进程之间形成一种头尾相接的循环等待资源关系。 在GCD中,主要的死锁就是当前串行队列里面同步执行当前串行队列。解决的方法就是将同步的串行队列放到另外一个线程执行。 在举例说明之前,我们先来回顾下GCD的中的任务派发和队列。 (1)任务派发 任务派发方式 说明 dispatch_sync() 同步执行,完成了它预定的任务后才返回,阻塞当前线程 dispatch_async() 异步执行,会立即返回,预定的任务会完成但不会等它完成,不阻塞当前线程 (2)队列种类 队列种类 说明 串行队列

洛谷P3327 [SDOI2015]约数个数和 【莫比乌斯反演】

落爺英雄遲暮 提交于 2020-03-16 12:51:25
题目 设d(x)为x的约数个数,给定N、M,求 \(\sum_{i = 1}^{N} \sum_{j = 1}^{M} d(ij)\) 输入格式 输入文件包含多组测试数据。第一行,一个整数T,表示测试数据的组数。接下来的T行,每行两个整数N、M。 输出格式 T行,每行一个整数,表示你所求的答案。 输入样例 2 7 4 5 6 输出样例 110 121 提示 1<=N, M<=50000 1<=T<=50000 题解 好神的题【 是我太弱吧 】 首先上来就伤结论。。 题目所求 \[ans = \sum_{i = 1}^{N} \sum_{j = 1}^{M} d(ij)\] 有一个这样的结论: \[d(ij) = \sum_{x|i}\sum_{y|j} [gcd(x,y) == 1]\] 那么就转化为了: \[ans =\sum_{i = 1}^{N} \sum_{j = 1}^{M} \sum_{x|i}\sum_{y|j} [gcd(x,y) == 1]\] 我们考虑对于每一对互质的x、y,x会被枚举 \(\lfloor \frac{N}{x} \rfloor\) 次,y会被枚举 \(\lfloor \frac{M}{y} \rfloor\) 次 所以有 \[ans =\sum_{i = 1}^{N} \sum_{j = 1}^{M} \lfloor \frac{N}{i}

欧几里德算法(辗转相除)证明

狂风中的少年 提交于 2020-03-16 02:07:27
过了这么久,终于知道了辗转相处的证明了,以前只是记住了,但不是真的很理解,现在写一下它的证明,以便下次忘了的时候看一下。辗转相除是求两个数的最大公约数的。 要证这个定理成立,只需要证明 gcd(a, b) = gcd(b, a % b) 就行了 证明:令a % b = r, 所以a = k * b + r, 所以r = a - k * b,假设d为a,b的一个公约数,那么 d|a, d|b,(d|a的意思就是d整除a,也就是a能被d整除),所以a - k * b 也一定能被d整除,即 d|r, 也就是 d|(a % b), 因此d也是b 和 (a % b)的公约数,因此a,b 的公约数和b, (a%b)的公约数也是一样的,其最大公约数也一定相同,所以gcd(a, b) = gcd(b, a % b); 所以有了这个等式之后,基本上就算完了,还有一步就是怎么到最后求个具体的数,当b等于0时候就可以了,因为最后递归好多还是和原来的那个公寓数是相同的,最后有0了,他俩的最大公约数就是他本身了,也就是a了,用递归代码如下 1 int gcd(int a, int b) 2 { 3 return (b == 0 ? a : gcd(b, a % b)); 4 } 来源: https://www.cnblogs.com/Howe-Young/p/4329362.html

Hankson的趣味题

雨燕双飞 提交于 2020-03-15 11:21:13
【题目描述】 今天在课堂上,老师讲解了如何求两个正整数c[1]和c[2]的最大公约数和最小公倍数。现 在Hankson认为自己已经熟练地掌握了这些知识,他开始思考一个“求公约数”和“求公 倍数”之类问题的“逆问题”,这个问题是这样的:已知正整数a[0]、a[1]、b[0]、b[1],设某未知正整 数x满足: 1.x和a[0]的最大公约数是a[1]; 2.x和b[0]的最小公倍数是b[1]。 Hankson的“逆问题”就是求出满足条件的正整数x。但稍加思索之后,他发现这样的 x并不唯一,甚至可能不存在。因此他转而开始考虑如何求解满足条件的x的个数。请你帮 助他编程求解这个问题。 【输入描述】 第一行为一个正整数n,表示有n组输入数据。接下来的n行每行一组输入数据,为四个正整数a[0]、a[1]、b[0]、b[1],每两个整数之间用一个空格隔开。输入数据保证a[0]能被a[1]整除,b[1]能被b[0]整除。 【输出描述】 每组输入数据的输出结果占一行,为一个整数。 对于每组数据:若不存在这样的x,请输出0; 若存在这样的x,请输出满足条件的x 的个数。 【样例输入】 2 41 1 96 288 95 1 37 1776 【样例输出】 6 2 【数据范围及提示】 样例解释: 第一组输入数据,x可以是9、18、36、72、144、288,共有6个; 第二组输入数据,x可以是48、1776

【JZOJ3780】【UVA1642】Magical GCD

我们两清 提交于 2020-03-15 06:17:06
题目大意: 给一个长度为 \(n\) 的数列,找到一个连续子序列使得子序列的公约数与长度的乘积最大,求这个最大值。 正文: 直接枚举 GCD 区间的右端点 \(r\) ,再枚举左端点 \(l(l<r)\) 计算 GCD,记录答案。 \(\texttt{50}\) 分。 可以通过上一个枚举的右端点 \((r-1)\) 计算过的 GCD 区间更新当前区间就可以了,这些操作可以通过链表实现。 代码: for (scanf ("%d", &t); t--; ) { memset (a, 0, sizeof(a)); memset (b, 0, sizeof(b)); memset (last_, 0, sizeof(last_)); memset (next_, 0, sizeof(next_)); ans = 0; scanf ("%lld", &n); for (int i = 1; i <= n; i++) { scanf ("%lld", &a[i]); b[i] = a[i]; last_[i] = i - 1, next_[i] = i + 1; } for (int r = 1; r <= n; r++) { for (int l = 1; l <= r; l = next_[l]) { b[l] = gcd(b[l], a[r]); ans = max(ans, (r -

同余问题(一)——扩展欧几里得exgcd

♀尐吖头ヾ 提交于 2020-03-13 15:36:33
前言 扩展欧几里得 算法是一个很好的解决同余问题的算法,非常实用。 欧几里得算法 简介 欧几里得算法,又称辗转相除法。 主要用途 求最大公因数 \(gcd\) 。 公式 \(gcd(a,b)=gcd(b,a\%b)\) 公式证明 \(a\) 可以表示成 \(a=kb+a\%b\) ( \(k\) 为自然数)。 假设 \(g\) 是 \(a,b\) 的一个公约数,则有 \(g|a, g|b\) 。 \(\because a\%b=a-kb\) , \(\therefore g|(a\%b),\therefore g\) 是 \(b,a\%b\) 的公约数。 综上所述, \(a,b\) 和 \(b,a\%b\) 的公约数是一样的,其 \(gcd\) 也必然相等。 代码实现 inline int gcd(int x,int y) {return y?gcd(y,x%y):x;} 扩展欧几里得算法 简介 扩展欧几里得建立于欧几里得算法的基础上。 (该算法的升级版 徐xgcd 有待 XuRuiYang 奆佬发明) 主要用途 对于已知a,b求解x,y使其满足ax+by=gcd(a,b)。 解法 我们可以对 \((a,b)\) 不断辗转相除。 根据欧几里得算法,最后剩下的两个数一定为 \((gcd(a,b),0)\) , 显然,此时 \(x=1,y=0\) 是原式的一组解。 现在,我们需要考虑

欧几里德算法

橙三吉。 提交于 2020-03-12 17:21:45
欧几里德算法 欧几里德算法又称辗转相除法,用于计算两个整数 a,b 的最大公约数。其计算原理依赖于下面的定理:   定理: gcd(a,b) = gcd(b,a % b)   证明: a 可以表示成 a = kb + r ,则 r = a % b   假设 d 是 a,b 的一个公约数,则有    d|a, d|b ,而 r = a - kb ,因此 d|r   因此 d 是 (b,a % b) 的公约数   假设 d 是 (b,a % b) 的公约数,则    d | b , d |r ,但是 a = kb +r   因此 d 也是 (a,b) 的公约数 因此 (a,b) 和 (b,a mod b) 的公约数是一样的,其最大公约数也必然相等,得证 ;  欧几里德算法就是根据这个原理来做的,其算法用 C++ 语言描述为:  int Gcd(int a, int b)    {    if(b == 0) return a; return Gcd(b, a % b);    } 迭代法    int Gcd(int a, int b)     {     while(b != 0)     {   int r = b;    b = a % b;     a = r;     }     return a;     } 扩展欧几里德算法是用来在已知 a, b 求解一组 x , y

leetcode 1071. 字符串的最大公因子

痞子三分冷 提交于 2020-03-12 09:27:21
思路:看了一个大佬的题解,非常的巧妙。 首先,str1和str2一定是由相同的子串构成的,只不过子串的数量不同而已,所以str1+str2==str2+str1. 若不满足前面的等式,那么表示没有相同的子串。 其次,假设str1的长度是m构成,str2的长度是n. 那么最大的子串长度一定能同时整除m,n。 其实最大长度就是gcd(m,n)。 class Solution { public: string gcdOfStrings(string str1, string str2) { int len1=str1.size(),len2=str2.size(); if(str2+str1!=str1+str2) return ""; return str1.substr(0,gcd(len1,len2)); } int gcd(int a,int b) { if(b==0) return a; return gcd(b,a%b); } }; 来源: CSDN 作者: untilyouydc 链接: https://blog.csdn.net/qq_40774175/article/details/104811252

Interval GCD(线段树区间增加、区间查询)

被刻印的时光 ゝ 提交于 2020-03-09 15:27:16
题目描述 给定一个长度为N的数列A,以及M条指令 (N≤5*10^5, M<=10^5),每条指令可能是以下两种之一: “C l r d”,表示把 A[l],A[l+1],…,A[r] 都加上 d。 “Q l r”,表示询问 A[l],A[l+1],…,A[r] 的最大公约数(GCD)。 输入 第一行两个整数N,M,第二行N个整数Ai,接下来M行每条指令的格式如题目描述所示。 输出 对于每个询问,输出一个整数表示答案。 样例输入 5 5 1 3 5 7 9 Q 1 5 C 1 5 1 Q 1 5 C 3 3 6 Q 2 4 样例输出 1 2 4 算法提示: 我们知道gcd(x,y)=gcd(x,y-x)。它可以进一步扩展到三个数的情况:gcd(x,y,z)=gcd(x,y-x,z-y)。实际上,给性质对任意多个整数都成立。 因此,我们可以构造一个长度为N的新数列B,其中 B[i]=a[i]-a[i-1],B[1]可为任意值。数列B称为A的差分序列。 用线段树维护序列B的区间最大公约数。 这样一来,询问“Q l r”,就等于求出gcd(A[i],ask(1,l+1,r))。 在指令“C l r d”下,只有B[r+1]被减掉了d,所以在维护B的线段树上只进行两次单点修改即可。另外,询问时需要数列A中的值,可额外用一个支持“区间增加,单点查询”的树状数组对数列A进行维护。 完整代码: