洛谷 P5435 基于值域预处理的快速 GCD 题解

算法

虽然标题上写着堂堂正正,辉煌的几个字就是本题正解,但是还有比正解更优的做法。

前置知识:二进制 GCD

当你学完二进制 GCD 之后,就可以直接写出代码,但是要记住取模。

代码

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector> 

using namespace std;

typedef unsigned long long ull;
const int mod = 998244353;
int a[5003], b[5003], n;

ull gcd(ull a, ull b) { // 二进制 GCD
	ull az = __builtin_ctz(a), bz = __builtin_ctz(b);
	ull z = min(az, bz);
	b >>= bz;
	while (a) {
		a >>= az;
		int tmp = a - b;
		az = __builtin_ctz(tmp); 
		b = min(a, b), a = abs(tmp);
	} 
	return b << z;
}

signed main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
	for (int i = 1; i <= n; i++) scanf("%d", &b[i]);
	for (int i = 1; i <= n; i++) {
		ull ans = 0, k = i;
		for (int j = 1; j <= n; j++) {
		    // 注意取模
			ans = (ans + (k * gcd(a[i], b[j]) % mod)) % mod;
			k = k * i % mod;
		}
		printf("%llu\n", ans);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值