BZOJ2987:Earthquake(类欧几里德算法)

Sol

(n=lfloorfrac{c}{a} floor)
问题转化为求

[sum_{i=0}^{n}lfloorfrac{c-ax}{b} floor+1=sum_{i=0}^{n}lfloorfrac{-ax+b+c}{b} floor ]

考虑一般性的问题

[f(a,b,c,n)=sum_{i=0}^{n}lfloorfrac{ax+b}{c} floor,c e 0 ]

  1. (cle 0),那么 (f(a,b,c,n)=f(-a,-b,-c,n))
  2. (a<0)(b<0),那么

[f(a,b,c,n)=f(a~mod~c + c, b~mod~c + c, c, n) + frac{n(n + 1)}{2} (lfloorfrac{a}{c} floor - 1) + (n + 1)(lfloorfrac{b}{c} floor - 1) ]

  1. (a>=c)(b>=c),那么

[f(a,b,c,n)=f(a~mod~c, b~mod~c, c, n) + frac{n(n + 1)}{2}lfloorfrac{a}{c} floor + (n + 1)lfloorfrac{b}{c} floor ]

  1. 最后 (0le a<c)(0le b<c)
    (m=lfloorfrac{an+b}{c} floor)
    那么

[sum_{i=0}^{n}lfloorfrac{ai+b}{c} floor=sum_{i=0}^{n}sum_{j=1}^{m}[lfloorfrac{ai+b}{c} floorge j]=sum_{i=0}^{n}sum_{j=0}^{m-1}[lfloorfrac{ai+b}{c} floorge j+1] ]

[=sum_{i=0}^{n}sum_{j=0}^{m-1}[aige cj+c-b]=sum_{i=0}^{n}sum_{j=0}^{m-1}[ai> cj+c-b-1] ]

[=sum_{i=0}^{n}sum_{j=0}^{m-1}[i> lfloorfrac{cj+c-b-1}{a} floor]=sum_{i=0}^{m-1}(n-lfloorfrac{ci+c-b-1}{a} floor) ]

[=nm-sum_{i=0}^{m-1}lfloorfrac{ci+c-b-1}{a} floor=nm-f(c,c-b-a,a,m-1) ]

边界是 (a=0) 或者 (nle 1)

这个题直接代入就好了

# include <bits/stdc++.h>
using namespace std;
typedef long long ll;

inline ll Gcd(ll x, ll y) {
	if (!x || !y) return x + y;
	return !y ? x : Gcd(y, x % y);
}

inline ll Solve(ll a, ll b, ll c, ll n) {
	if (!a) return (n + 1) * (b / c);
	if (!n) return b / c;
	if (n == 1) return (a + b) / c + b / c;
	if (c < 0) return Solve(-a, -b, -c, n);
	register ll d = abs(Gcd(Gcd(a, b), c));
	a /= d, b /= d, c /= d;
	if (a >= c || b >= c) return Solve(a % c, b % c, c, n) + n * (n + 1) / 2 * (a / c) + (n + 1) * (b / c);
	if (a < 0 || b < 0) return Solve(a % c + c, b % c + c, c, n) + n * (n + 1) / 2 * (a / c - 1) + (n + 1) * (b / c - 1);
	register ll m = (a * n + b) / c;
	return n * m - Solve(c, c - b - 1, a, m - 1);
}

ll a, b, c, n;

int main() {
	scanf("%lld%lld%lld", &a, &b, &c), n = c / a;
	printf("%lld
", Solve(-a, c + b, b, n));
    return 0;
}
原文地址:https://www.cnblogs.com/cjoieryl/p/10091774.html