类欧几里得算法

难得有空写学习笔记。

写这篇笔记的时候同学在机房互吐冰红茶。

问题:给定 n,a,b,c,请你分别求出 f(a,b,c,n)=i=0nai+bcg(a,b,c,n)=i=0niai+bch(a,b,c,n)=i=0nai+bc2


Part 1

考虑如何求 f(a,b,c,n),分成两部分求解:

a,b>c 时:

f(a,b,c,n)=i=0namodc×i+bmodc+ac×c×i+bc×cc

把常数项提出来即为 f(a,b,c,n)=ac×n(n+1)2+bc×(n+1)+i=0namodc×i+bmodcc

换一下求和部分:f(a,b,c,n)=ac×n(n+1)2+bc×(n+1)+f(amodc,bmodc,c,n),发现此时 amodc,bmodc 都小于 c

a,b<c 时:

f(a,b,c,n)=i=0nj=0ai+bc11

j 提到外面去变为 f(a,b,c,n)=j=0an+bc1i=0n[j<ai+bc]

考虑转换条件式:

j<ai+bcjai+bc1ijc+cbai>jc+cb1a

m=an+bc,则 f(a,b,c,n)=j=0m1i=0n[i>jc+cb1a]

最后 f(a,b,c,n)=j=0m1(njc+cb1a),即为 f(a,b,c,n)=nmf(c,cb1,a,m1)


Part 2

考虑求 g(a,b,c,n)

同样的思路可以算出当 a,b>c 时: g(a,b,c,n)=n(n+1)(2n+1)6×ac+n(n+1)2×bc+g(amodc,bmodc,c,n)

a,b<c 时,令 m=an+bct=jc+cb1a

g(a,b,c,n)=j=0m1i=0ni[i>t]

不难得到 g(a,b,c,n)=j=0m112(n(n+1)t(t+1))

提出常数项得到 g(a,b,c,n)=12(nm(n+1)j=0m1tj=0m1t2)

最后把 t 带进去得到 g(a,b,c,n)=12(nm(n+1)f(c,cb1,a,m1)h(c,cb1,a,m1))


Part 3

考虑求 h(a,b,c,n)

a,b>c 时:

考虑取模变形:h(a,b,c,n)=i=0n(iac+bc+amodc×i+bmodcc)2

展开可得:

h(a,b,c,n)=i=0n(i2ac2+bc2+amodc×i+bmodcc2+2iacbc+2iacamodc×i+bmodcc+2bcamodc×i+bmodcc)

经过整理可得:

h(a,b,c,n)=h(amodc,bmodc,c,n)+S2(n)ac2+(n+1)bc2+2S1(n)acbc+2acg(amodc,bmodc,c,n)+2bcf(amodc,bmodc,c,n)

其中 S1(n)=n(n+1)2,S2(n)=n(n+1)(2n+1)6

a,b<c 时:

一个简单有用的 trick:x2=2x(x+1)2x=2i=1xix

然后带入原式:h(a,b,c,n)=i=0n2(j=0ai+bcj)ai+bc

同样地,令 m=an+bct=jc+cb1a

做最后的变形:

h(a,b,c,n)=2i=0nj=0ai+bc1(j+1)f(a,b,c,n)

                    =2j=0m1(j+1)(nt)f(a,b,c,n)

                    =2j=0m1(j+1)(njc+cb1a)f(a,b,c,n)

                    =nm(m+1)2f(c,cb1,a,m1)2g(c,cb1,a,m1)f(a,b,c,n)


最后一起考虑 a=0 时的情况,也就是把含 a 的项去掉即可。

三个公式一起递归求解即可,时间复杂度为 O(logn)

代码回家再写。

全机房在摸鱼。我也要颓颓颓


Code

#include<bits/stdc++.h> 
#define int long long 
#define x first 
#define y second 
#define il inline 
#define debug() puts("-----") 
using namespace std; 
typedef pair<int,int> pii; 
il int read(){ 
	int x=0,f=1; char ch=getchar(); 
	while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } 
	while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); 
	return x*f; 
} 
const int Mod=998244353; 
const int inv2=499122177;  
const int inv6=166374059; 
struct Node{ int f,g,h; };  
il int s1(int x){ return x*(x+1)%Mod*inv2%Mod; } 
il int s2(int x){ return x*(x+1)%Mod*(2*x+1)%Mod*inv6%Mod; }  
il Node solve(int a,int b,int c,int n){ 
	Node ans,res; 
	int Ac=a/c,Bc=b/c; 
	int Ac2=Ac*Ac%Mod,Bc2=Bc*Bc%Mod; 
	if(a==0){ 
		ans.f=Bc*(n+1)%Mod; 
		ans.g=Bc*s1(n)%Mod; 
		ans.h=Bc2*(n+1)%Mod; 
		return ans; 
	} if(a>=c||b>=c){ 
		res=solve(a%c,b%c,c,n); 
		ans.f=(res.f+Ac*s1(n)%Mod+Bc*(n+1)%Mod)%Mod; 
		ans.g=(res.g+Ac*s2(n)%Mod+Bc*s1(n)%Mod)%Mod; 
		ans.h=(res.h+Ac2*s2(n)%Mod+Bc2*(n+1)%Mod)%Mod; 
		ans.h=(ans.h+2*(s1(n)*Ac%Mod*Bc%Mod+Ac*res.g%Mod+Bc*res.f%Mod)%Mod)%Mod; 
		return ans;  
	} int m=(a*n+b)/c; 
	res=solve(c,c-b-1,a,m-1); 
	ans.f=(n*m%Mod-res.f)%Mod; 
	ans.g=(n*m%Mod*(n+1)%Mod-res.f-res.h)%Mod*inv2%Mod; 
	ans.h=(n*m%Mod*(m+1)%Mod-2*(res.f+res.g)%Mod-ans.f)%Mod; 
	ans.f=(ans.f+Mod)%Mod,ans.g=(ans.g+Mod)%Mod,ans.h=(ans.h+Mod)%Mod;  
	return ans; 
} 
il void work(){ 
	int n=read(),a=read(),b=read(),c=read(); 
	Node ans=solve(a,b,c,n); printf("%lld %lld %lld\n",ans.f,ans.h,ans.g); 
} 
signed main(){ 
	int T=read(); 
	while(T--) work(); 
	return 0; 
} 
posted @   Celestial_cyan  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示