A. Row GCD (Gcd辗转相除法)

本文介绍了一种求解多个整数间最大公约数(GCD)的高效算法。通过预处理两个特定整数之间的GCD,可以快速计算出任意整数与这组特定整数间的最大公约数。

传送门

题意:给你n个数a_1,a_2,a_3,...,a_n,和m个数b_1,b_2,b_3,...,b_n,

让你求每个 j (1<=j<=m)  的GCD(a_1+b_j,a_2+b_j,a_3+b_j,...,a_n+b_j);

思路:从最基础的求最大公约数的原理开始走:

GCD(x,y)=GCD(x,y-x);

那么看整体,GCD(a_1+b_j,a_2+b_j,a_3+b_j,...,a_n+b_j)

=GCD(a_1+b_j,GCD(a_1+b_j,a_2+b_j),GCD(a_1+b_j,a_3+b_j),....,GCD(a_1+b_j,a_n+b_j) )

=GCD(a_1+b_j,a_2-a_1,a_3-a_1,...,a_n-a_1);

那么我们 提前预处理取得GCD(|a_2-a_1|,|a_3-a_1|,...,|a_n-a_1|)(取绝对值是因为取得结果有一部分可能是负数的),然后对每一个a_1+b_j取GCD就可以了。

/**
 *  ┏┓   ┏┓+ +
 * ┏┛┻━━━┛┻┓ + +
 * ┃       ┃
 * ┃   ━   ┃ ++ + + +
 *  ████━████+
 *  ◥██◤ ◥██◤ +
 * ┃   ┻   ┃
 * ┃       ┃ + +
 * ┗━┓   ┏━┛
 *   ┃   ┃ + + + +Code is far away from  
 *   ┃   ┃ + bug with the animal protecting
 *   ┃    ┗━━━┓ 神兽保佑,代码无bug 
 *   ┃  	    ┣┓
 *    ┃        ┏┛
 *     ┗┓┓┏━┳┓┏┛ + + + +
 *    ┃┫┫ ┃┫┫
 *    ┗┻┛ ┗┻┛+ + + +
 */

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <map>
#define sc_int(x) scanf("%d", &x)
#define sc_ll(x) scanf("%lld", &x)
#define pr_ll(x) printf("%lld", x)
#define pr_ll_n(x) printf("%lld\n", x)
#define pr_int_n(x) printf("%d\n", x)
#define ll long long
using namespace std;

const int N = 1000000 + 100;
int n, m, h;
ll s[N], b[N];

int main()
{
	int t;
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		sc_ll(s[i]);
	for (int i = 1; i <= m; i++)
		sc_ll(b[i]);

	ll res = 0;
	for(int i =2;i<=n;i++)
	{
		if(i==2)res=abs(s[i]-s[1]);
		else res=__gcd(res,abs(s[i]-s[1]));
	}
	for(int i =1;i<=m;i++)
	cout<<__gcd(res,s[1]+b[i])<<" ";
	return 0;
}

ll gcd2(ll a, ll b) { if (a < 0) a = -a; if (b < 0) b = -b; while (b != 0) { ll temp = b; b = a % b; a = temp; } rt a; } //计算三元最大公因数(gcd2) ll gcd3(ll a, ll b, ll c) { rt gcd2(gcd2(a, b), c); } //计算n元最大公因数(数组[1,n);嵌gcd2) ll gcdn(ll arr[], in n) { if (n == 0) rt 0; ll result = arr[0]; for (in i = 1; i < n; ++i) { result = gcd2(result, arr[i]); if (result == 1) br; } rt result; } //计算二元最小公倍数(gcd2) ll lcm2(ll a, ll b) { if (a == 0 || b == 0) rt 0; ll ga = a < 0 ? -a : a; ll gb = b < 0 ? -b : b; ll g = gcd2(ga, gb); rt ga / g * gb; } //计算三元最小公倍数(嵌lcm2) ll lcm3(ll a, ll b, ll c) { rt lcm2(lcm2(a, b), c); } //计算n元最小公倍数(数组[1,n);嵌lcm2) ll lcmn(ll arr[], in n) { if (n == 0) rt 1; ll result = arr[0]; for (in i = 1; i < n; ++i) { result = lcm2(result, arr[i]); if (result == 0) br; } rt result; } //计算n元最小公倍数(数组[1,n);嵌lcm2;取模) ll lcmn_mod(ll arr[], in n) { if (n == 0) rt 1; ll result = arr[0]; for (in i = 1; i < n; ++i) { result = lcm2(result, arr[i]); if (result == 0) br; result %= MOD; } rt result; }in matrix_rank(in A[][MAX_LEN], in m, in n) { in rank = 0; for (in col = 0; col < n && rank < m; col++) { in pivot_row = -1; for (in row = rank; row < m; row++) { if (A[row][col] != 0) { pivot_row = row; break; } } if (pivot_row == -1) continue; if (pivot_row != rank) { for (in j = 0; j < n; j++) { in temp = A[rank][j]; A[pivot_row][j] = A[rank][j]; A[rank][j] = temp; } } for (in row = rank + 1; row < m; row++) { if (A[row][col] == 0) continue; in a = A[rank][col]; in b = A[row][col]; in l = lcm(a, b); if (l == 0) continue; in mult1 = l / a; in mult2 = l / b; for (in j = col; j < n; j++) { A[row][j] = mult2 * A[row][j] - mult1 * A[rank][j]; } } rank++; } rt rank; }
12-01
使用sql语句完成任务:(一)存储函数的创建与使用 1.定义一个函数,计算两个数的最大公约数。 a) 输入两个整数。 b) 输出最大公约数。 c) 请用两种不同的方法实现gcd1()gcd2()。 d) 调用c)中的两个函数,查找45和18的最大公约数。 e) 提示:可以通过辗转相除法找到两个数的最大公约数,流程图6-1如下。 图 6 1最大公约数流程图 2.课程的评分通常分为百分制和等级制。创建存储函数do_convert(),实现其转换,要求: a) 输入指定百分制成绩。 b) 输出对应的等级制成绩。 c) 转换规则,如果>=90分则为优秀,80-90(包含80)为良好,70-80(包含70)为中等,60-70(包含60)为及格,否则为不及格。 d) 查询该函数是否创建成功。 e) 使用d)中的函数,查询A课程学生的等级成绩,查询输出如下。 输出如下: 学生学号 学生姓名 学生班级号 等级制成绩 (二)触发器的创建与使用 1.使用触发器实现单列取值的范围约束。要求tbl_student学生表的生日字段要么为空,要么必须大于等于‘1900-01-01‘,小于今年。 a) 实现触发器birthday_check_trigger对表的更新约束。 b) 请找两个例子,验证触发器是否是实现了检查约束。 2.在进销存数据库创建触发器,对数据进行一致性约束。当销售表tbl_sell增加一条数据时,商品表的tbl_goods库存量减去对应的销量。当进货表tbl_receive增加一条数据时,商品表的库存量增加对应的进货数量。
05-30
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值