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

本文探讨了一个复杂的数学算法问题,涉及求和、取整操作及模运算,通过定义函数f(a,b,c,n),解决了特定条件下的数学求和问题。文章详细介绍了如何根据a、b、c的正负及大小关系转换问题,最终简化为计算nm减去另一个函数调用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Sol

n=⌊ca⌋n=\lfloor\frac{c}{a}\rfloorn=ac
问题转化为求
∑i=0n⌊c−axb⌋+1=∑i=0n⌊−ax+b+cb⌋\sum_{i=0}^{n}\lfloor\frac{c-ax}{b}\rfloor+1=\sum_{i=0}^{n}\lfloor\frac{-ax+b+c}{b}\rfloori=0nbcax+1=i=0nbax+b+c
考虑一般性的问题

f(a,b,c,n)=∑i=0n⌊ax+bc⌋,c≠0f(a,b,c,n)=\sum_{i=0}^{n}\lfloor\frac{ax+b}{c}\rfloor,c\ne 0f(a,b,c,n)=i=0ncax+bc̸=0

  1. c≤0c\le 0c0,那么 f(a,b,c,n)=f(−a,−b,−c,n)f(a,b,c,n)=f(-a,-b,-c,n)f(a,b,c,n)=f(a,b,c,n)
  2. a&lt;0a&lt;0a<0b&lt;0b&lt;0b<0,那么
    f(a,b,c,n)=f(a mod c+c,b mod c+c,c,n)+n(n+1)2(⌊ac⌋−1)+(n+1)(⌊bc⌋−1)f(a,b,c,n)=f(a~mod~c + c, b~mod~c + c, c, n) + \frac{n(n + 1)}{2} (\lfloor\frac{a}{c}\rfloor - 1) + (n + 1)(\lfloor\frac{b}{c}\rfloor - 1)f(a,b,c,n)=f(a mod c+c,b mod c+c,c,n)+2n(n+1)(ca1)+(n+1)(cb1)
  3. a&gt;=ca&gt;=ca>=cb&gt;=cb&gt;=cb>=c,那么
    f(a,b,c,n)=f(a mod c,b mod c,c,n)+n(n+1)2⌊ac⌋+(n+1)⌊bc⌋f(a,b,c,n)=f(a~mod~c, b~mod~c, c, n) + \frac{n(n + 1)}{2}\lfloor\frac{a}{c}\rfloor + (n + 1)\lfloor\frac{b}{c}\rfloorf(a,b,c,n)=f(a mod c,b mod c,c,n)+2n(n+1)ca+(n+1)cb
  4. 最后 0≤a&lt;c0\le a&lt;c0a<c0≤b&lt;c0\le b&lt;c0b<c
    m=⌊an+bc⌋m=\lfloor\frac{an+b}{c}\rfloorm=can+b
    那么
    ∑i=0n⌊ai+bc⌋=∑i=0n∑j=1m[⌊ai+bc⌋≥j]=∑i=0n∑j=0m−1[⌊ai+bc⌋≥j+1]\sum_{i=0}^{n}\lfloor\frac{ai+b}{c}\rfloor=\sum_{i=0}^{n}\sum_{j=1}^{m}[\lfloor\frac{ai+b}{c}\rfloor\ge j]=\sum_{i=0}^{n}\sum_{j=0}^{m-1}[\lfloor\frac{ai+b}{c}\rfloor\ge j+1]i=0ncai+b=i=0nj=1m[cai+bj]=i=0nj=0m1[cai+bj+1]
    =∑i=0n∑j=0m−1[ai≥cj+c−b]=∑i=0n∑j=0m−1[ai&gt;cj+c−b−1]=\sum_{i=0}^{n}\sum_{j=0}^{m-1}[ai\ge cj+c-b]=\sum_{i=0}^{n}\sum_{j=0}^{m-1}[ai&gt; cj+c-b-1]=i=0nj=0m1[aicj+cb]=i=0nj=0m1[ai>cj+cb1]
    =∑i=0n∑j=0m−1[i&gt;⌊cj+c−b−1a⌋]=∑i=0m−1(n−⌊ci+c−b−1a⌋)=\sum_{i=0}^{n}\sum_{j=0}^{m-1}[i&gt; \lfloor\frac{cj+c-b-1}{a}\rfloor]=\sum_{i=0}^{m-1}(n-\lfloor\frac{ci+c-b-1}{a}\rfloor)=i=0nj=0m1[i>acj+cb1]=i=0m1(naci+cb1)
    =nm−∑i=0m−1⌊ci+c−b−1a⌋=nm−f(c,c−b−a,a,m−1)=nm-\sum_{i=0}^{m-1}\lfloor\frac{ci+c-b-1}{a}\rfloor=nm-f(c,c-b-a,a,m-1)=nmi=0m1aci+cb1=nmf(c,cba,a,m1)
    边界是 a=0a=0a=0 或者 n≤1n\le 1n1

这个题直接代入就好了

# 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\n", Solve(-a, c + b, b, n));
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值