[BZOJ2987]Earthquake:类欧几里得算法

分析

类欧的式子到底是谁推的啊怎么这么神仙啊orz!

简单说一下这道题,题目中的约束条件可以转化为:

[y leq frac{c-ax}{b} ]

有负数怎么办啊?转化一下:

[y leq frac{ax+c\%a}{b} ]

唔姆,好像差不多。

枚举(x),可以看成那个类欧的式子((sum_{i=0}^{n} lfloor frac{ai+b}{c} floor))。

然后就能上类欧搞了,注意边界条件是(c=0)时返回(0)

代码

#include <bits/stdc++.h>
#define rin(i,a,b) for(register int i=(a);i<=(b);++i)
#define irin(i,a,b) for(register int i=(a);i>=(b);--i)
#define trav(i,a) for(register int i=head[a];i;i=e[i].nxt)
typedef long long LL;
using std::cin;
using std::cout;
using std::endl;

inline LL read(){
	LL x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}

LL a,b,c;

LL gcd(LL n,LL a,LL b,LL c){
	if(!c) return 0;
	if(a>=c||b>=c) return n*(n+1)/2*(a/c)+(n+1)*(b/c)+gcd(n,a%c,b%c,c);
	else return n*((a*n+b)/c)-gcd((a*n+b)/c-1,c,c-b-1,a);
}

int main(){
	a=read(),b=read(),c=read();
	printf("%lld
",gcd(c/a,a,c%a,b)+c/a+1);
	return 0;
}
原文地址:https://www.cnblogs.com/ErkkiErkko/p/10257319.html