1. 程式人生 > >[BZOJ2987]Earthquake:類歐幾里得演算法

[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} \rfloor\))。

然後就能上類歐搞了,注意邊界條件是\(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\n",gcd(c/a,a,c%a,b)+c/a+1);
    return 0;
}