【模板】类欧几里得算法

博客分享了作者通过推导实现欧几里得算法的过程,提供了详细链接供读者查看,强调亲自推导能加深对该算法的理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接


csdn不支持align,我也不想再重新打一遍了
就直接贴个链接
链接:https://pan.baidu.com/s/1DL4JCpNogKXV5CcYbEKGdQ
提取码:rnyz

这是我按照题解的思路一边推一边写的,写完后感觉有了很深的理解

感觉推导只需要稍微了解一下和式就能理解,大家也可以自己手推一遍


#include <cstdio>
using namespace std;

#define dd c=getchar()
int read() {int s=0,w=1;char c;while (dd,c>'9' || c<'0') if (c=='-') w=-1;while (c>='0' && c<='9') s=s*10+c-'0',dd;return s*w;}
#undef dd

const int P = 998244353,inv2=499122177,inv6=166374059;
struct node {
	int f,g,h;
};

void Ad(int &x, int y) {x+=y; if (x>=P) x-=P;}
void Dec(int &x, int y) {x-=y; if (x<0) x+=P;}
node solve(int a, int b, int c, int n) {
	node s;
	int A=a/c,B=b/c;
	int S1=1ll*(n+1)*n%P*inv2%P;
	int S2=1ll*(2ll*n%P+1)*(n+1)%P*n%P*inv6%P;
	if (!a) {
		s.f=1ll*(n+1)*B%P;
		s.g=1ll*(n+1)*B%P*B%P;
		s.h=1ll*S1*B%P;
	}
	else if (a >= c || b >= c){
		node t = solve(a%c, b%c, c, n);
		s = t;
		Ad(s.f, (1ll*S1*A%P+1ll*(n+1)*B%P)%P);
		Ad(s.g, 2ll*A%P*t.h%P);
		Ad(s.g, 2ll*B%P*t.f%P);
		Ad(s.g, 1ll*S2*A%P*A%P);
		Ad(s.g, 2ll*S1*A%P*B%P);
		Ad(s.g, 1ll*(n+1)*B%P*B%P);
		Ad(s.h, 1ll*S2*A%P);
		Ad(s.h, 1ll*S1*B%P);
	}
	else {
		int M = (1ll*a*n+b)/c;
		node t = solve(c, c-b-1, a, M-1);
		s.f = (1ll*n*M%P-t.f+P)%P;
		s.g = (1ll*n*M%P*(M+1)%P - s.f + P)%P;
		Dec(s.g, 2ll*t.h%P);
		Dec(s.g, 2ll*t.f%P);
		s.h = 1ll*n*M%P*(n+1)%P;
		Dec(s.h, (t.g+t.f)%P);
		s.h = 1ll*s.h*inv2%P;
	}
	return s;
}

int T,a,b,c,n;
int main() {
	T = read();
	while (T--) {
		n = read(); a = read(), b = read(), c = read();
		node s = solve(a, b, c, n);
		printf("%d %d %d\n",s.f,s.g,s.h);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值