类欧几里得算法的一种几何解释
本文内容来自我的 OI 笔记,由于技术原因只能导出为图片格式。
代码实现
LL pws(int n,int k){
if(!k) return (LL)n%MOD;
if(k==1) return (LL)n*(LL)(n+1)/2ll%MOD;
if(k==2) return (LL)n*(LL)(n+1)%MOD*(LL)(2*n+1)%MOD*inv6%MOD;
}
void calc(int a,int b,int c,int n,LL &f,LL &g,LL &h){// a,c,n>=0
if(!a){
int nn=max(0,b/c);
f=(LL)nn*(LL)n%MOD;
g=(LL)nn*pws(n,1)%MOD;
h=pws(nn,1)*(LL)n%MOD;
}
else if(b<0){
int mv=(-b+a-1)/a,nb=b+mv*a;
if(n<=mv)
f=g=h=0ll;
else{
calc(a,nb,c,n-mv,f,g,h);
(g+=f*mv)%=MOD;
}
if(n>=mv){
(f+=(LL)(nb/c))%=MOD;
(g+=(LL)mv*(LL)(nb/c))%=MOD;
(h+=pws(nb/c,1))%=MOD;
}
}
else if(a>=c){
LL da=a/c;
LL df=da*pws(n,1);
LL dg=da*pws(n,2);
LL dh=da*inv2%MOD*pws(n,1)-da*da%MOD*inv2%MOD*pws(n,2);// +da*g reserved
calc(a-c*da,b,c,n,f,g,h);
(f+=df)%=MOD;
(g+=dg)%=MOD;
(h+=dh+g*da)%=MOD;
}
else{
int nn=((LL)a*(LL)n+(LL)b)/(LL)c;
calc(c,-b-1,a,nn,f,g,h);
f=((LL)n*(LL)nn-f)%MOD;
LL ng=(pws(n,1)*(LL)nn-h)%MOD,nh=(pws(nn,1)*(LL)n-g)%MOD;
g=ng;h=nh;
}
}
void answer(int a,int b,int c,int n,LL &f,LL &g,LL &h){
++n;
b-=a;
calc(a,b,c,n,f,g,h);
f=(f+MOD*MOD)%MOD;g=(g+MOD*MOD)%MOD;h=(h+MOD*MOD)%MOD;
h=(h*2ll+MOD-f)%MOD;
g=(g+MOD-f)%MOD;
}