Number Theory - class Euclidean algorithm

Introduced

solve

 

 

Seeking f (a, b, c, n) with O (logn) algorithm.

We've seen this formula and formula are not the same look. With rounding down of the formulas easy to think of number theory block, but the block number theory seems not apply to this sum. But we can do some preprocessing.

If a> = c or b> = c, means may be a, b to c modulo a simplified problem:

 

 The problem has returned a <situation <c && b c, and the expression conditions for i <n, contributions to the floor ((a * i + b ) / c), this time we  will contribute to the condition to do the conversion, the contribution becomes form a new sub-conditions:

 

 Now more than a variable j, i since the contribution of poor demand, then we can go to seek contribution j, in which case we restrict the transfer type, and where n in the above limit i upper bound, but i limit j upper bound. To engage j  , j placed on the first contribution formula yard, forced by n  limit j upper bound

 

 The j <floor ((a * i + b) / c) for simplification stars

 

 

This is a recursive formula. And you find a, c numerator and denominator for a location, and can repeat the process. First modulo recursively. This is a toss of the division process, which is named after the class Euclidean algorithm.

Easy to find the time complexity is O (log (n-)) .

 

Spread

begging

 

 For the function g

As before, modulo, as Σi * i = (n + 1) * (2 * n + 1) * n / 6, it is

 

 

 

 For the function h

Also first modulo

 

 

 

 

 

 Because the three functions intersect, so the template is obtained together

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int P = 998244353;
int i2 = 499122177, i6 = 166374059;
struct data {
  data() { f = g = h = 0; }
  int f, g, h;
};  // 三个函数打包
data calc(int n, int a, int b, int c) {
  int ac = a / c, bc = b / c, m = (a * n + b) / c, n1 = n + 1, n21 = n * 2+ . 1 ; 
  Data D; 
  IF (A == 0 )   // iteration to the bottom 
  { 
    DF = N1 * BC% P; 
    DG = BC% * n-P * N1 * I2% P% P; 
    DH = BC * BC% N1% * P P;
     return D; 
  } 
  IF (A> B = C ||> = C)   // modulo 
  { 
    DF = n-P * N1 * I2% AC% P% P * BC * N1 +% P; 
    DG = AC * n-% P * N1% P * N21% P * I6% P + BC * n-% P * N1% P * I2% P; 
    DH = AC * AC% P * n-% P * N1% P * n21% P * i6% P +
          bc * bc % P * n1 % P + ac * bc % P * n % P * n1 % P;
    d.f %= P, d.g %= P, d.h %= P;

    data e = calc(n, a % c, b % c, c);  // 迭代

    d.h += e.h + 2 * bc % P * e.f % P + 2 * ac % P * e.g % P;
    d.g += e.g, d.f += e.f;
    d.f %= P, d.g %= P, d.h %= P;
    return d;
  }
  data e = calc(m - 1, c, c - b - 1, a);
  d.f = n * m % P - e.f, d.f = (d.f % P + P) % P;
  d.g = m * n % P * n1 % P - e.h - e.f, d.g = (d.g * i2 % P + P) % P;
  d.h = n * m % P * (m + 1) % P - 2 * e.g - 2 * e.f - d.f;
  d.h = (d.h % P + P) % P;
  return d;
}
int T, n, a, b, c;
signed main() {
  scanf("%lld", &T);
  while (T--) {
    scanf("%lld%lld%lld%lld", &n, &a, &b, &c);
    data ans = calc(n, a, b, c);
    printf("%lld %lld %lld\n", ans.f, ans.h, ans.g);
  }
  return 0;
}

 

 

 The main contribution to learn to use the Conditional Sum transfer method, and further simplification of n squared, there are three templates.

 

Guess you like

Origin www.cnblogs.com/2462478392Lee/p/12450889.html