BZOJ-2987 Earthquake(类欧几里得算法)

题目描述

  给定 \(A,B,C\),求满足方程 \(Ax+By\leq C\) 的 非负 整数解 \((x,y)\)(\(A,B\leq 10^9,C\leq \min(A,B)\times 10^9\))。

分析

  考虑枚举 \(y\),移项得:\(0\leq y\leq \lfloor\frac{C-Ax}{B}\rfloor\),当 $ x=0$ 时,\(y\) 枚举的上界为 \(\lfloor\frac{C}{A}\rfloor\)。

  这相当于求线段 \(y=\frac{C-Ax}{B}(0\leq y\leq \lfloor\frac{C}{A}\rfloor)\) 在第一象限和 \(x,y\) 正半轴内整点的数量。

  把斜率为负调整成斜率为正的线段,原来线段的两端点为 \((0,\frac{C}{B}),(\lfloor\frac{C}{A}\rfloor,\frac{C-A\lfloor\frac{C}{A}\rfloor}{B})\),将两端点对换,分别为 \((0,\frac{C-A\lfloor\frac{C}{A}\rfloor}{B}),(\lfloor\frac{C}{A}\rfloor,\frac{C}{B})\),此时线段为 \(y=\frac{A}{B}x+\frac{C-A\lfloor\frac{C}{A}\rfloor}{B}=\frac{Ax+C\% A}{B}\)。

  问题即求(加 \(1\) 是因为 \(x=0\) 时也是合法解):

\[\sum_{i=0}^{\lfloor\frac{C}{A}\rfloor}\Big(\Big\lfloor\frac{Ax+C\%A}{B}\Big\rfloor+1\Big)=\sum_{x=0}^{\lfloor\frac{C}{A}\rfloor}\Big(\Big\lfloor\frac{Ax+C\%A+B}{B}\Big\rfloor\Big) \]

  考虑一个一般性问题:

\[f(a,b,c,n)=\sum_{i=0}^{n}\Big\lfloor\frac{ai+b}{c}\Big\rfloor \]

  \(1.\) 当 \(a\geq c\) \(b\geq c\) 时,

BZOJ-2987 Earthquake(类欧几里得算法)

  \(2.\) 当 \(a<c\) \(b<c\) 时,

BZOJ-2987 Earthquake(类欧几里得算法)

  可以发现右边递归成为子问题,继续一轮操作即可。边界条件:\(a=0\)。

代码

#include<bits/stdc++.h>
using namespace std;
long long A,B,C;
long long solve(long long a,long long b,long long c,long long n)
{
    if(a==0)
        return (n+1)*(b/c);
    if(a>=c||b>=c)
        return solve(a%c,b%c,c,n)+(a/c)*n*(n+1)/2+(b/c)*(n+1);
    long long m=(a*n+b)/c;
    return n*m-solve(c,c-b-1,a,m-1);
}
int main()
{
    cin>>A>>B>>C;
    cout<<solve(A,C%A+B,B,C/A)<<endl;
    return 0;
}
上一篇:「题解」洛谷 P2424 约数和


下一篇:「题解」洛谷 P2261 [CQOI2007]余数求和