模版类欧几里得
模版类欧几里得
这个东西,说他没用,确实极少会见到。去推这个柿子也完全是因为兴趣(顺便练习一下推柿子的能力),整体来说,这个推柿子难度不高,基本上有小学知识就能够理解。
这里知有代数解法,几何意义本人太菜了还不会。
Base 题目
给定
Part :
先来讨论第一个,在这里我们设其为
(这里用
主要套路有两个:取模和化贡献。
取模
取模意义在于能够把
显然有
发现第二项和第四项都是可以整除
前面的东西就是
化贡献
接下来考虑如何快速计算一个
我们把
为了方便,设
最后一步是因为我们接下来要用到大于的形式比较好化简。代回原式有
这样就成功形成一个递归的形式了,观察到这个递归形式很像
Part :
这两个需要一起解,先设
注意和原题面的顺序不太一样。
老套路来一遍,就不加注释了
得到几乎一摸一样的取模形式。
具体计算也先尝试一样的套路试一下
这时候出现了一点小问题,后面多了一个
回忆一下
再来一遍!不过这次有一丢丢复杂。
设
那么只剩下最后一步了,还是尝试老套路,我们利用一个看起来很废话的东西:
进行推导
收工!
代码比较丑
#include<bits/stdc++.h>
using namespace std;
#define int long long
int mod=998244353;
int qpow(int x,int y){
int res=1;
for(;y;y>>=1){
if(y&1)res=res*x%mod;
x=x*x%mod;
}
return res;
}
int inv2=qpow(2,mod-2),inv6=qpow(6,mod-2);
struct node{
int f,g,h;
};
node calc(int a,int b,int c,int n){
node res,tmp;
if(a==0){
res.f=(n+1)*(b/c)%mod;
res.g=n*(n+1)%mod*inv2%mod*(b/c)%mod;
res.h=(n+1)*(b/c)%mod*(b/c)%mod;
return res;
}
if(a>=c||b>=c){
tmp=calc(a%c,b%c,c,n);
res.f=((n*(n+1)%mod*inv2%mod*(a/c)+(n+1)*(b/c)%mod)%mod+tmp.f)%mod;
res.g=((n*(n+1)%mod*(2*n+1)%mod*inv6%mod*(a/c)%mod
+n*(n+1)%mod*inv2%mod*(b/c)%mod)%mod
+tmp.g)%mod;
res.h=((((n*(n+1)%mod*(2*n+1)%mod*inv6%mod*(a/c)%mod*(a/c)%mod
+(n+1)*(b/c)%mod*(b/c)%mod)%mod
+n*(n+1)%mod*(a/c)%mod*(b/c)%mod)%mod
+tmp.h+2*(a/c)%mod*tmp.g%mod)%mod
+2*(b/c)%mod*tmp.f%mod)%mod;
return res;
}
int m=((a*n)+b)/c;
tmp=calc(c,c-b-1,a,m-1);
res.f=(n*m%mod-tmp.f+mod)%mod;
res.g=((n*m%mod*(n+1)%mod-tmp.h+mod)%mod-tmp.f+mod)%mod*inv2%mod;
res.h=(((n*m%mod*(m+1)%mod-2*tmp.g%mod+mod)%mod-2*tmp.f%mod+mod)%mod-res.f+mod)%mod;
return res;
}
int T,A,B,C,N;
signed main(){
cin.tie(0),cout.tie(0),ios::sync_with_stdio(false);
cin>>T;
while(T--){
cin>>N>>A>>B>>C;
node R=calc(A,B,C,N);
cout<<R.f<<" "<<R.h<<" "<<R.g<<"\n";
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下