Loading

类欧几里得

前置定理:

[a/b]≥c  == a≥bc

[a/b]≤c  == a≤bc

[a/b]>c  == abc

[a/b]<c  == a<bc

[b/c] == [(b+c-1)/c] == [(b-c+1)/c]

 


 

f()= Σ [(ai+b)/c] 

1: 当a≥c 或 b≥c时

[(ai+b)/c]=[ ((a%c)i+(b%c))/c]+[a/c]i+[b/c];

f()=f(a%c,b%c,c,n) + (n(n+1))/2 *[a/c] + (n+1)*[b/c]

2:当a<c && b<c 时

令m=[(an+b)/c];

f()=nm - f(c,c-b-1,a,m-1)

ll S(ll k) { return (k*(k+1)/2ll)%MOD; }
ll f(ll a,ll b,ll c,ll n) {
    if(!a)return 0;
    if(a>=c||b>=c)
        return ((a/c)*S(n)%MOD+(n+1)*(b/c)%MOD+f(a%c,b%c,c,n))%MOD;
    ll m=(a*n+b)/c;
    return (m*n%MOD-f(c,c-b-1,a,m-1)+MOD)%MOD;
}
View Code
ll f(ll a,ll b,ll c,ll n){
    if(a==0) return (n+1)*(b/c);
    if(a<c&&b<c){
        ll m=(a*n+b)/c;
        if(m==0) return 0;
        return n*m-f(c,c-b-1,a,m-1);
    }
    return f(a%c,b%c,c,n)+(n+1)*(b/c)+((n+1)/(1+(n&1)))*(n/(2-(n&1)))*(a/c);
}
View Code

 


 

g()=Σ i [(ai+b)/c]

1: 当a≥c 或 b≥c时

g()=g(a%c,b%c,c,n) + (n(n+1)(2n+1)/6) *[a/c] + (n(n+1)/2) * [b/c]

2:当a<c && b<c 时

g()=( mn(n+1)-f(c,c-b-1,a,m-1)-h(c,c-b-1,a,m-1) )/2

 


 

h()=Σ [(ai+b)/c]2

1: 当a≥c 或 b≥c时

h()=h(a%c,b%c,c,n)+( n(n+1)(2n+1)/6 ) *[a/c]2+ (n+1) * [b/c]2+2[b/c]f(a%c,b%c,c,n)+2[a/c]g(a%c,b%c,c,n)+[a/c][b/c](n+1)n

2:当a<c && b<c 时

h()=mn(m+1) - 2g(c,c-b-1,a,m-1) - 2f(c,c-b-1,a,m-1) - f(a,b,c,n)


 

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=998244353;
const ll inv2=499122177;
const ll inv6=166374059;
struct node {
    ll f,g,h;
};
node solve(ll a,ll b,ll c,ll n) {
    node ans,tmp;
    if(a==0) {
        ans.f=(n+1)*(b/c)%mod;
        ans.g=(b/c)*n%mod*(n+1)%mod*inv2%mod;
        ans.h=(n+1)*(b/c)%mod*(b/c)%mod;
        return ans;
    }
    if(a>=c||b>=c) {
        tmp=solve(a%c,b%c,c,n);
        ans.f=(tmp.f+(a/c)*n%mod*(n+1)%mod*inv2%mod+(b/c)*(n+1)%mod)%mod;
        ans.g=(tmp.g+(a/c)*n%mod*(n+1)%mod*(2*n+1)%mod*inv6%mod+(b/c)*n%mod*(n+1)%mod*inv2%mod)%mod;
        ans.h=((a/c)*(a/c)%mod*n%mod*(n+1)%mod*(2*n+1)%mod*inv6%mod+
            (b/c)*(b/c)%mod*(n+1)%mod+(a/c)*(b/c)%mod*n%mod*(n+1)%mod+
            tmp.h+2*(a/c)%mod*tmp.g%mod+2*(b/c)%mod*tmp.f%mod)%mod;
        return ans;
    }
    ll m=(a*n+b)/c;
    tmp=solve(c,c-b-1,a,m-1);
    ans.f=(n*(m%mod)%mod-tmp.f)%mod;
    ans.g=(n*(n+1)%mod*(m%mod)%mod-tmp.f-tmp.h)%mod*inv2%mod;
    ans.h=(n*(m%mod)%mod*((m+1)%mod)%mod-2*tmp.g-2*tmp.f-ans.f)%mod;
    return ans;
}

int main() {
    ll t;
    cin>>t;
    while(t--) {
        ll n,a,b,c;
        cin>>n>>a>>b>>c;
        node ans=solve(a,b,c,n);
        printf("%lld %lld %lld\n",(ans.f+mod)%mod,(ans.h+mod)%mod,(ans.g+mod)%mod);
    }
    return 0;
}

 

posted @ 2019-10-04 16:36  qinuna  阅读(145)  评论(0编辑  收藏  举报