传送门
关于 f
关于 g
暴力拆开发现
但 a < c 的时候有点头凸
类似套路的可以推到
关于 h
跟 f 一样,不想打了
#include
using namespace std;
typedef long long ll;
const int Mod = 998244353, inv2 = (Mod+1)/2, inv6 = (Mod+1)/6;
ll mul(ll a, ll b){ return a * b % Mod;}
ll add(ll a, ll b){ return (a + b) >= Mod ? a + b - Mod : a + b; }
ll n, a, b, c; int T;
struct Node{ ll f, g, h;};
Node Solve(ll a, ll b, ll c, ll n){
if(c == 0) return (Node){0, 0, 0};
if(a >= c || b >= c){
Node tmp = Solve(a % c, b % c, c, n);
ll f = add(add(mul(mul(a/c, n), mul(n+1, inv2)), mul(b/c, n+1)), tmp.f);
ll g = mul(mul(a/c, a/c), mul(mul(inv6, n), mul(n+1, n*2+1)));
g = add(g, mul(mul(b/c, b/c), n+1));
g = add(g, mul(mul(a/c, b/c), mul(n, n+1)));
g = add(g, mul(mul(2, a/c), tmp.h));
g = add(g, mul(mul(2, b/c), tmp.f));
g = add(g, tmp.g);
ll h = mul(mul(a/c, n), mul(mul(n+1, n*2+1), inv6));
h = add(h, mul(mul(b/c, n), (mul(n+1, inv2))));
h = add(h, tmp.h);
return (Node){f, g, h};
}
ll fn = (a * n + b) / c;
Node tmp = Solve(c, c - b - 1, a, fn - 1);
ll f = add(mul(n, fn), Mod - tmp.f);
ll g = mul(mul(n, fn), fn+1);
g = add(g, Mod - mul(2, add(tmp.h, tmp.f)));
g = add(g, Mod - f);
ll h = mul(n, mul(n+1, fn));
h = add(h, Mod - add(tmp.f, tmp.g)); h = mul(h, inv2);
return (Node){f, g, h};
}
int main(){
scanf("%d", &T);
while(T--){
scanf("%lld%lld%lld%lld", &n, &a, &b, &c);
Node ans = Solve(a, b, c, n);
cout << ans.f << " " << ans.g <<" " << ans.h << "\n";
} return 0;
}