大致题意: 求满足(Ax+Byle C)的(x,y)的非负整数解个数。
推式子
显然由原式变形得到:
[Ax+Byle CLeftrightarrow Axle C-ByLeftrightarrow xlelfloorfrac{C-By}A
floor
]
于是发现,如果我们枚举(y),就会得到答案是这样一个式子:
[sum_{i=0}^{lfloorfrac CB
floor}(lfloorfrac{C-Bi}A
floor+1)
]
考虑到减号是一个比较烦人的东西,实际上此题中完全可以把(C-Bi)看作是([0,C])中和(C)模(B)同余的数,也就是由原式转而得到:
[sum_{i=0}^{lfloorfrac CB
floor}(lfloorfrac {(C\%B)+Bi}A
floor+1)
]
如果我们设:
[f(n,A,B,C)=sum_{i=0}^n(lfloorfrac {Bi+C}A
floor+1)
]
不难发现,题目中要我们求的就是(f(lfloorfrac CB floor,A,B,C\%B)),且这显然可以当类欧几里得算法板子来做。
类欧几里得算法
当(B=0)时:
[f(n,a,b,c)=sum_{i=0}^n(lfloorfrac CA
floor+1)=(n+1)(lfloorfrac CA
floor+1)
]
当(Bge A)或(Cge A)时:
[egin{align}f(n,a,b,c)&=sum_{i=0}^n(lfloorfrac{(B\%A)i+(C\%A)}A
floor+lfloorfrac BA
floor i+lfloorfrac CA
floor+1)\&=f(n,A,B\%A,C\%A)+frac{n(n+1)}2lfloorfrac BA
floor+(n+1)lfloorfrac CA
floorend{align}
]
当(B<A,C<A)时:
令(m=lfloorfrac{Bn+C}A floor),即(lfloorfrac{Bi+C}A floor)能取到的最大值。
[egin{align}f(n,a,b,c)&=sum_{i=0}^nsum_{j=1}^m[lfloorfrac{Bi+C}A
floorge j]+(n+1)\&=sum_{i=0}^nsum_{j=0}^{m-1}[Bi+C+1>jA+A]+(n+1)\&=sum_{i=0}^nsum_{j=0}^{m-1}[i>lfloorfrac{jA+A-C-1}B
floor]+(n+1)\&=sum_{j=0}^{m-1}(n-lfloorfrac{jA+A-C-1}B
floor)+(n+1)\&=nm-f(m-1,B,A,A-C-1)+(n+m+1)end{align}
]
于是递归求解即可,复杂度证明类似于欧几里得算法。
代码
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define LL long long
using namespace std;
I LL Get(Con LL& n,CI A,CI B,CI C)//类欧几里得算法
{
if(!B) return (n+1)*(C/A+1);//B=0
if(B>=A||C>=A) return Get(n,A,B%A,C%A)+n*(n+1)/2*(B/A)+(n+1)*(C/A);//B>=A或C>=A
LL m=(B*n+C)/A;return n*m-Get(m-1,B,A,A-C-1)+n+m+1;//B<A,C<A
}
int main()
{
int A,B;LL C;return scanf("%d%d%lld",&A,&B,&C),printf("%lld",Get(C/B,A,B,C%B)),0;
}