类欧几里得算法学习笔记

引入

类欧几里得算法可以在 O ( l o g n ) O(logn) O(logn)形如如下问题的:

∑ i = 0 n ⌊ a i + b c ⌋ \sum_{i=0}^n\lfloor\frac{ai+b}{c}\rfloor i=0ncai+b

f ( n , a , b , c ) = ∑ i = 0 n ⌊ a i + b c ⌋ f(n,a,b,c)=\sum_{i=0}^n\lfloor\frac{ai+b}{c}\rfloor f(n,a,b,c)=i=0ncai+b

首先,先把 a ≥ c a\geq c ac b ≥ c b\geq c bc的情况通过对 c c c取模化为 a < c , b < c a<c,b<c a<c,b<c的情况
f ( n , a , b , c ) = ∑ i = 0 n ⌊ ( c ⌊ a c ⌋ + ( a m o d    c ) ) i + c ⌊ b c ⌋ + ( b m o d    c ) c ⌋ f(n,a,b,c)=\sum_{i=0}^n\lfloor\frac{(c\lfloor\frac{a}{c}\rfloor+(a\mod c))i+c\lfloor\frac{b}{c}\rfloor+(b\mod c)}{c}\rfloor f(n,a,b,c)=i=0nc(cca+(amodc))i+ccb+(bmodc)

= ∑ i = 0 n ⌊ a c ⌋ i + ⌊ b c ⌋ + ⌊ ( a m o d    c ) i + ( b m o d    c ) c ⌋ =\sum_{i=0}^n\lfloor\frac{a}{c}\rfloor i+\lfloor\frac{b}{c}\rfloor+\lfloor\frac{(a\mod c)i+(b\mod c)}{c}\rfloor =i=0ncai+cb+c(amodc)i+(bmodc)

= ⌊ a c ⌋ n ( n + 1 ) 2 + ( n + 1 ) ⌊ b c ⌋ + f ( n , a m o d    c , b m o d    c , c ) =\lfloor\frac{a}{c}\rfloor \frac{n(n+1)}{2}+(n+1)\lfloor\frac{b}{c}\rfloor+f(n,a\mod c,b\mod c,c) =ca2n(n+1)+(n+1)cb+f(n,amodc,bmodc,c)

m = ⌊ a n + b c ⌋ m=\lfloor\frac{an+b}{c}\rfloor m=can+b

接下来考虑求后半部分的值:

f ( n , a , b , c ) = ∑ i = 0 n ⌊ a i + b c ⌋ f(n,a,b,c)=\sum_{i=0}^n\lfloor\frac{ai+b}{c}\rfloor f(n,a,b,c)=i=0ncai+b

= ∑ i = 0 n ∑ j = 0 ⌊ a i + b c ⌋ − 1 1 =\sum_{i=0}^n\sum_{j=0}^{\lfloor\frac{ai+b}{c}\rfloor-1}1 =i=0nj=0cai+b11

交换求和号:

= ∑ j = 0 m − 1 ∑ i = 0 n [ j < ⌊ a i + b c ⌋ ] =\sum_{j=0}^{m-1}\sum_{i=0}^n[j<\lfloor\frac{ai+b}{c}\rfloor] =j=0m1i=0n[j<cai+b]
接下来考虑拆掉里边的取整:

= ∑ j = 0 m − 1 ∑ i = 0 n [ j + 1 ≤ a i + b c ] =\sum_{j=0}^{m-1}\sum_{i=0}^n[j+1\leq \frac{ai+b}{c}] =j=0m1i=0n[j+1cai+b]

= ∑ j = 0 m − 1 ∑ i = 0 n [ c j + c − b − 1 < a i ] =\sum_{j=0}^{m-1}\sum_{i=0}^n[cj+c-b-1< ai] =j=0m1i=0n[cj+cb1<ai]

= ∑ j = 0 m − 1 ∑ i = 0 n [ ⌊ c j + c − b − 1 a ⌋ < i ] =\sum_{j=0}^{m-1}\sum_{i=0}^n[\lfloor \frac{cj+c-b-1}{a}\rfloor < i] =j=0m1i=0n[acj+cb1<i]

这样做的好处是里边的i独立了,符合的i的个数可以直接算出来

= ∑ j = 0 m − 1 n − ⌊ c j + c − b − 1 a ⌋ =\sum_{j=0}^{m-1}n-\lfloor \frac{cj+c-b-1}{a}\rfloor =j=0m1nacj+cb1

后边是一个递归的形式

= n m − f ( m − 1 , c , c − b − 1 , a ) =nm-f(m-1,c,c-b-1,a) =nmf(m1,c,cb1,a)

可以发现,我们把a和c的位置交换了,也就是一个类似于辗转相除的过程,复杂度和欧几里得算法的复杂度都是 O ( l o g n ) O(logn) O(logn),这也是类殴名字的由来。

代码大致长这个样子:

LL f(LL n,LL a,LL b,LL c)
{
	LL ac=a/c,bc=b/c;
	LL m=(a*n+b)/c;
	if(a==0)
	{
		return (n+1)*bc;
	}
	if(a>=c||b>=c)
	{
		return f(n,a%c,b%c,c)+n*(n+1)/2*ac+(n+1)*bc;
	}
	return n*m-f(m-1,c,c-b-1,a);
}

拓展


g ( n , a , b , c ) = ∑ i = 0 n ⌊ a i + b c ⌋ i g(n,a,b,c)=\sum_{i=0}^n\lfloor\frac{ai+b}{c}\rfloor i g(n,a,b,c)=i=0ncai+bi

h ( n , a , b , c ) = ∑ i = 0 n ⌊ a i + b c ⌋ 2 h(n,a,b,c)=\sum_{i=0}^n\lfloor\frac{ai+b}{c}\rfloor^2 h(n,a,b,c)=i=0ncai+b2

求g

首先类似的,通过对c取模使得a,b小于c
g ( n , a , b , c ) = g ( n , a m o d    c , b m o d    c , c ) + ⌊ a c ⌋ n ( n + 1 ) ( 2 n + 1 ) 6 + ⌊ b c ⌋ n ( n + 1 ) 2 g(n,a,b,c)=g(n,a\mod c,b\mod c,c)+\lfloor \frac{a}{c}\rfloor\frac{n(n+1)(2n+1)}{6}+\lfloor \frac{b}{c}\rfloor \frac{n(n+1)}{2} g(n,a,b,c)=g(n,amodc,bmodc,c)+ca6n(n+1)(2n+1)+cb2n(n+1)
然后仿照f的求法
g ( n , a , b , c ) = ∑ i = 0 n ⌊ a i + b c ⌋ i g(n,a,b,c)=\sum_{i=0}^n\lfloor\frac{ai+b}{c}\rfloor i g(n,a,b,c)=i=0ncai+bi

= ∑ i = 0 n ∑ j = 0 ⌊ a i + b c ⌋ − 1 i =\sum_{i=0}^n\sum_{j=0}^{\lfloor\frac{ai+b}{c}\rfloor-1}i =i=0nj=0cai+b1i

m = ⌊ a n + b c ⌋ m=\lfloor\frac{an+b}{c}\rfloor m=can+b

= ∑ j = 0 m − 1 ∑ i = 0 n [ j < ⌊ a i + b c ⌋ ] i =\sum_{j=0}^{m-1}\sum_{i=0}^n[j<\lfloor\frac{ai+b}{c}\rfloor]i =j=0m1i=0n[j<cai+b]i

= ∑ j = 0 m − 1 ∑ i = 0 n [ ⌊ c j + c − b − 1 a ⌋ < i ] i =\sum_{j=0}^{m-1}\sum_{i=0}^n[\lfloor \frac{cj+c-b-1}{a}\rfloor < i]i =j=0m1i=0n[acj+cb1<i]i

p = ⌊ c j + c − b − 1 a ⌋ p=\lfloor \frac{cj+c-b-1}{a}\rfloor p=acj+cb1

= ∑ j = 0 m − 1 ( p + 1 + n ) ( n − p ) 2 =\sum_{j=0}^{m-1}\frac{(p+1+n)(n-p)}{2} =j=0m12(p+1+n)(np)

= 1 2 ∑ j = 0 m − 1 n + n 2 − p 2 − p =\frac{1}{2}\sum_{j=0}^{m-1}n+n^2-p^2-p =21j=0m1n+n2p2p

= 1 2 ( m n ( n + 1 ) − ∑ j = 0 m − 1 p − ∑ j = 0 m − 1 p 2 ) =\frac{1}{2}(mn(n+1)-\sum_{j=0}^{m-1}p-\sum_{j=0}^{m-1}p^2) =21(mn(n+1)j=0m1pj=0m1p2)

= 1 2 ( m n ( n + 1 ) − f ( m − 1 , c , c − b − 1 , a ) − h ( m − 1 , c , c − b − 1 , a ) ) =\frac{1}{2}(mn(n+1)-f(m-1,c,c-b-1,a)-h(m-1,c,c-b-1,a)) =21(mn(n+1)f(m1,c,cb1,a)h(m1,c,cb1,a))

求h

首先还是取模,可以得到:
h ( n , a , b , c ) = h ( n , a m o d    c , b m o d    c , c ) h(n,a,b,c)=h(n,a\mod c,b\mod c,c) h(n,a,b,c)=h(n,amodc,bmodc,c)
+ 2 ⌊ b c ⌋ f ( n , a m o d    c , b m o d    c , c ) + 2 ⌊ a c ⌋ g ( n , a m o d    c , b m o d    c , c ) +2\lfloor \frac{b}{c}\rfloor f(n,a\mod c,b\mod c,c)+2\lfloor \frac{a}{c}\rfloor g(n,a\mod c,b\mod c,c) +2cbf(n,amodc,bmodc,c)+2cag(n,amodc,bmodc,c)
+ ⌊ a c ⌋ 2 n ( n + 1 ) ( 2 n + 1 ) 6 + ⌊ b c ⌋ 2 ( n + 1 ) + ⌊ a c ⌋ ⌊ b c ⌋ n ( n + 1 ) +\lfloor \frac{a}{c}\rfloor^2\frac{n(n+1)(2n+1)}{6}+\lfloor \frac{b}{c}\rfloor^2(n+1)+\lfloor \frac{a}{c}\rfloor \lfloor \frac{b}{c}\rfloor n(n+1) +ca26n(n+1)(2n+1)+cb2(n+1)+cacbn(n+1)

接着求 h ( n , a , b , c ) h(n,a,b,c) h(n,a,b,c)

m = ⌊ a n + b c ⌋ , p = ⌊ c j + c − b − 1 a ⌋ m=\lfloor\frac{an+b}{c}\rfloor,p=\lfloor \frac{cj+c-b-1}{a}\rfloor m=can+b,p=acj+cb1

为了避免出现求和号相乘的情况,我们换一个形式

n 2 = 2 n ( n + 1 ) 2 − n = 2 ∑ i = 1 n i − n n^2=2\frac{n(n+1)}{2}-n=2\sum_{i=1}^ni-n n2=22n(n+1)n=2i=1nin

所以
h ( n , a , b , c ) = ∑ i = 0 n ( 2 ∑ j = 1 ⌊ a i + b c ⌋ j − ⌊ a i + b c ⌋ ) h(n,a,b,c)=\sum_{i=0}^n(2\sum_{j=1}^{\lfloor\frac{ai+b}{c}\rfloor}j-\lfloor\frac{ai+b}{c}\rfloor) h(n,a,b,c)=i=0n(2j=1cai+bjcai+b)

= 2 ∑ i = 0 n ∑ j = 1 ⌊ a i + b c ⌋ j − f ( n , a , b , c ) =2\sum_{i=0}^n\sum_{j=1}^{\lfloor\frac{ai+b}{c}\rfloor}j-f(n,a,b,c) =2i=0nj=1cai+bjf(n,a,b,c)

= 2 ∑ i = 0 n ∑ j = 0 ⌊ a i + b c ⌋ − 1 ( j + 1 ) − f ( n , a , b , c ) =2\sum_{i=0}^n\sum_{j=0}^{\lfloor\frac{ai+b}{c}\rfloor-1}(j+1)-f(n,a,b,c) =2i=0nj=0cai+b1(j+1)f(n,a,b,c)

只看前面
= ∑ j = 0 m − 1 ( j + 1 ) ∑ i = 0 n [ j < ⌊ a i + b c ⌋ ] =\sum_{j=0}^{m-1}(j+1)\sum_{i=0}^n[j<\lfloor\frac{ai+b}{c}\rfloor] =j=0m1(j+1)i=0n[j<cai+b]

= ∑ j = 0 m − 1 ( j + 1 ) ∑ i = 0 n [ ⌊ c j + c − b − 1 a ⌋ < i ] =\sum_{j=0}^{m-1}(j+1)\sum_{i=0}^n[\lfloor \frac{cj+c-b-1}{a}\rfloor < i] =j=0m1(j+1)i=0n[acj+cb1<i]

= ∑ j = 0 m − 1 ( j + 1 ) ∑ i = 0 n [ p < i ] =\sum_{j=0}^{m-1}(j+1)\sum_{i=0}^n[p < i] =j=0m1(j+1)i=0n[p<i]

= ∑ j = 0 m − 1 ( j + 1 ) ( n − p ) =\sum_{j=0}^{m-1}(j+1)(n-p) =j=0m1(j+1)(np)

= ∑ j = 0 m − 1 j n + n − j p − p =\sum_{j=0}^{m-1}jn+n-jp-p =j=0m1jn+njpp

= 1 2 n m ( m + 1 ) − ∑ i = 0 m − 1 i p − ∑ i = 0 p =\frac{1}{2}nm(m+1)-\sum_{i=0}^{m-1}i p-\sum_{i=0}p =21nm(m+1)i=0m1ipi=0p

= 1 2 n m ( m + 1 ) − g ( m − 1 , c , c − b − 1 , a ) − f ( m − 1 , c , c − b − 1 , a ) =\frac{1}{2}nm(m+1)-g(m-1,c,c-b-1,a)-f(m-1,c,c-b-1,a) =21nm(m+1)g(m1,c,cb1,a)f(m1,c,cb1,a)

总结

发现三个函数互相调用,但是函数参数的变化是相同的,因此可以把三个函数值存到一个结构体里一起递归,总时间复杂度 O ( l o g n ) O(logn) O(logn)

struct node
{
	LL f,g,h;
	node()
	{
		f=g=h=0;
	}
};
node Euclid(LL n,LL a,LL b,LL c)
{
	LL ac=a/c,bc=b/c;
	LL m=(a*n+b)/c;
	LL n1=n+1;
	LL n2=n*2+1;
	node ans;
	if(!a)
	{
		ans.f=bc*n1%mod;
		ans.g=n*n1%mod*inv2%mod*bc%mod;
		ans.h=bc*bc%mod*n1%mod;
		return ans; 
	}
	if(a>=c||b>=c)
	{
		ans.f=n*n1%mod*ac%mod*inv2%mod+n1*bc%mod;ans.f%=mod;
		ans.g=n*n1%mod*n2%mod*inv6%mod*ac%mod+bc*n%mod*n1%mod*inv2%mod;ans.g%=mod;
		ans.h=ac*ac%mod*n%mod*n1%mod*n2%mod*inv6%mod+bc*bc%mod*n1%mod+ac*bc%mod*n%mod*n1%mod;ans.h%=mod;
		node x=Euclid(n,a%c,b%c,c);
		ans.h+=2*bc%mod*x.f%mod+2*ac*x.g%mod+x.h;ans.h%=mod;
		ans.g+=x.g;ans.f+=x.f;ans.g%=mod;ans.f%=mod;
		return ans;		
	}
	node x=Euclid(m-1,c,c-b-1,a);
	ans.f=(n*m%mod-x.f+mod)%mod;
	ans.g=(m*n%mod*n1%mod-x.h-x.f+mod)%mod;
	ans.g=(ans.g%mod+mod)%mod;
	ans.g=ans.g*inv2%mod;
	ans.h=m*n%mod*(m+1)%mod-2*x.g%mod-2*x.f%mod-ans.f;
	ans.h=(ans.h%mod+mod)%mod;
	return ans;
}

例题

P5171 Earthquake

因为

a x + b y ≤ c ax+by\leq c ax+byc

所以

y ≤ ⌊ c − a x b ⌋ y\leq \lfloor \frac{c-ax}{b}\rfloor ybcax

那么对于一个固定的x,合法的y的个数为 ⌊ c − a x b ⌋ + 1 \lfloor \frac{c-ax}{b}\rfloor+1 bcax+1, + 1 +1 +1是因为y可以取0

同时,y=0时x最大,因此x的上线为 ⌊ c a ⌋ \lfloor \frac{c}{a}\rfloor ac

因此等价于

∑ x = 0 ⌊ c a ⌋ ⌊ c − a x b ⌋ + 1 \sum_{x=0}^{\lfloor \frac{c}{a}\rfloor}\lfloor \frac{c-ax}{b}\rfloor+1 x=0acbcax+1

不过因为 − a -a a小于0,所以不能直接上类欧的板子。

考虑加上一个 b x bx bx,再在外面减掉一个 x x x

∑ x = 0 ⌊ c a ⌋ ⌊ c + ( b − a ) x b ⌋ − x + 1 \sum_{x=0}^{\lfloor \frac{c}{a}\rfloor}\lfloor \frac{c+(b-a)x}{b}\rfloor-x+1 x=0acbc+(ba)xx+1

前面的直接用类欧,后边的可以直接算出来。

因为原题的限制对 a , b a,b a,b是对称的,因此为了保证 b − a ≥ 0 b-a\geq0 ba0,如果 b < a b<a b<a,交换一下就好了。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL f(LL n,LL a,LL b,LL c)
{
	LL ac=a/c,bc=b/c;
	LL m=(a*n+b)/c;
	if(a==0)
	{
		return (n+1)*bc;
	}
	if(a>=c||b>=c)
	{
		return f(n,a%c,b%c,c)+n*(n+1)/2*ac+(n+1)*bc;
	}
	return n*m-f(m-1,c,c-b-1,a);
}
int main()
{
	LL a,b,c;
	cin>>a>>b>>c;
	if(a>b) swap(a,b);
	LL m=(c/a);
	LL res=f(m,b-a,c,b)-m*(m+1)/2+m+1;
	cout<<res;
	return 0;
} 
P5172 Sum

x = r x=\sqrt r x=r ,注意这里没有取整

x x x为整数时

x x x是偶数,那答案为n

x x x是奇数,那当n为奇数时答案为-1,为偶数时答案为0

x x x不是整数

首先有一个小引理:

( − 1 ) n = 1 − 2 ( n m o d    2 ) = 1 − 2 ( n − 2 ⌊ n 2 ⌋ ) = 1 − 2 n + 4 ⌊ n 2 ⌋ (-1)^n=1-2(n\mod2)=1-2(n- 2\lfloor \frac{n}{2}\rfloor)=1-2n+4\lfloor \frac{n}{2}\rfloor (1)n=12(nmod2)=12(n22n)=12n+42n

所以原式为

∑ i = 1 n 1 − 2 ⌊ i x ⌋ + 4 ⌊ ⌊ i x ⌋ 2 ⌋ = n − 2 ∑ i = 1 n ⌊ i x ⌋ + 4 ∑ i = 1 n ⌊ i x 2 ⌋ \sum_{i=1}^n1-2\lfloor ix\rfloor+4\lfloor \frac{\lfloor ix \rfloor}{2}\rfloor =n-2\sum_{i=1}^n\lfloor ix\rfloor+4\sum_{i=1}^n\lfloor \frac{ix}{2}\rfloor i=1n12ix+42ix=n2i=1nix+4i=1n2ix


f ( n , a , b , c ) = ∑ i = 1 n ⌊ a x + b c i ⌋ f(n,a,b,c)=\sum_{i=1}^n\lfloor \frac{ax+b}{c} i\rfloor f(n,a,b,c)=i=1ncax+bi

那么题目所求即为, n − 2 f ( n , 1 , 0 , 1 ) + 4 f ( n , 1 , 0 , 2 ) n-2f(n,1,0,1)+4f(n,1,0,2) n2f(n,1,0,1)+4f(n,1,0,2)

p = a x + b c , q = ⌊ p ⌋ p=\frac{ax+b}{c},q=\lfloor p\rfloor p=cax+b,q=p

那么

f ( n , a , b , c ) = ∑ i = 1 n ⌊ p i ⌋ f(n,a,b,c)=\sum_{i=1}^n\lfloor pi\rfloor f(n,a,b,c)=i=1npi

= ∑ i = 1 n ⌊ p i − q i + q i ⌋ =\sum_{i=1}^n\lfloor pi-qi+qi\rfloor =i=1npiqi+qi

= ∑ i = 1 n ⌊ ( p − q ) i ⌋ + q i =\sum_{i=1}^n\lfloor (p-q)i\rfloor+qi =i=1n(pq)i+qi

= n ( n + 1 ) 2 q + ∑ i = 1 n ⌊ ( a x + b c − q ) i ⌋ =\frac{n(n+1)}{2}q+\sum_{i=1}^n\lfloor (\frac{ax+b}{c}-q)i\rfloor =2n(n+1)q+i=1n(cax+bq)i

= n ( n + 1 ) 2 q + f ( n , a , b − c q , c ) =\frac{n(n+1)}{2}q+f(n,a,b-cq,c) =2n(n+1)q+f(n,a,bcq,c)

这样当 q q q不为0的时候我们可以把q化为等于0的情况

f ( n , a , b , c ) = ∑ i = 1 n ∑ j = 1 ⌊ p n ⌋ [ j < p i ] f(n,a,b,c)=\sum_{i=1}^n\sum_{j=1}^{\lfloor pn \rfloor}[j<pi] f(n,a,b,c)=i=1nj=1pn[j<pi]

f ( n , a , b , c ) = ∑ i = 1 n ∑ j = 1 ⌊ p n ⌋ [ j p < i ] f(n,a,b,c)=\sum_{i=1}^n\sum_{j=1}^{\lfloor pn \rfloor}[\frac{j}{p}<i] f(n,a,b,c)=i=1nj=1pn[pj<i]

f ( n , a , b , c ) = ∑ j = 1 ⌊ p n ⌋ ∑ i = 1 n [ j p < i ] f(n,a,b,c)=\sum_{j=1}^{\lfloor pn \rfloor}\sum_{i=1}^n[\frac{j}{p}<i] f(n,a,b,c)=j=1pni=1n[pj<i]

f ( n , a , b , c ) = ∑ j = 1 ⌊ p n ⌋ n − ⌊ j p ⌋ f(n,a,b,c)=\sum_{j=1}^{\lfloor pn \rfloor}n-\lfloor \frac{j}{p} \rfloor f(n,a,b,c)=j=1pnnpj

f ( n , a , b , c ) = ∑ j = 1 ⌊ p n ⌋ n − ⌊ j a x + b c ⌋ f(n,a,b,c)=\sum_{j=1}^{\lfloor pn \rfloor}n-\lfloor \frac{j}{\frac{ax+b}{c}} \rfloor f(n,a,b,c)=j=1pnncax+bj

f ( n , a , b , c ) = ∑ j = 1 ⌊ p n ⌋ n − ⌊ c a x + b j ⌋ f(n,a,b,c)=\sum_{j=1}^{\lfloor pn \rfloor}n-\lfloor \frac{c}{ax+b}j \rfloor f(n,a,b,c)=j=1pnnax+bcj

考虑把x翻上去

f ( n , a , b , c ) = ∑ j = 1 ⌊ p n ⌋ n − ⌊ c ( a x − b ) ( a x + b ) ( a x − b ) j ⌋ f(n,a,b,c)=\sum_{j=1}^{\lfloor pn \rfloor}n-\lfloor \frac{c(ax-b)}{(ax+b)(ax-b)}j \rfloor f(n,a,b,c)=j=1pnn(ax+b)(axb)c(axb)j

f ( n , a , b , c ) = ⌊ p n ⌋ n − ∑ j = 1 ⌊ p n ⌋ ⌊ a c x − b c ) a 2 x 2 + b 2 j ⌋ f(n,a,b,c)=\lfloor pn \rfloor n-\sum_{j=1}^{\lfloor pn \rfloor}\lfloor \frac{acx-bc)}{a^2x^2+b^2}j \rfloor f(n,a,b,c)=pnnj=1pna2x2+b2acxbc)j

f ( n , a , b , c ) = ⌊ p n ⌋ n − ∑ j = 1 ⌊ p n ⌋ ⌊ a c x − b c ) a 2 r + b 2 j ⌋ f(n,a,b,c)=\lfloor pn \rfloor n-\sum_{j=1}^{\lfloor pn \rfloor}\lfloor \frac{acx-bc)}{a^2r+b^2}j \rfloor f(n,a,b,c)=pnnj=1pna2r+b2acxbc)j

f ( n , a , b , c ) = ⌊ p n ⌋ n − f ( ⌊ p n ⌋ , a c , − b c , a 2 r + b 2 ) f(n,a,b,c)=\lfloor pn \rfloor n-f(\lfloor pn \rfloor,ac,-bc,a^2r+b^2) f(n,a,b,c)=pnnf(pn,ac,bc,a2r+b2)

显然n是越来越小的,复杂度 O ( l o g n ) O(logn) O(logn)

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef double db;
db x;
LL r; 
LL gcd(LL a,LL b)
{
	if(!b) return a;
	return gcd(b,a%b);	
}
LL f(LL a,LL b,LL c,LL n)
{
	if(n==0) return 0;
	LL d=gcd(a,gcd(b,c));
	a/=d;b/=d;c/=d;
	LL t=(a*x+b)/c;
	if(t!=0) return n*(n+1)/2*t+f(a,b-c*t,c,n);
	LL k=(a*x+b)*n/c;
	return n*k-f(a*c,-b*c,a*a*r-b*b,k);	
}
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		LL n;
		scanf("%lld %lld",&n,&r);
		x=sqrt(r);
		int s=(int)x;
		if(1ll*s*s==r)
		{
			if(r%2==0) printf("%lld\n",n);
			else if(n%2==0) printf("0\n");
			else printf("-1\n");
		}
		else printf("%lld\n",n-2ll*f(1,0,1,n)+4ll*f(1,0,2,n));
	}
	return 0;
}
P5179 Fraction

一道有意思的题目

首先有一个小引理:使得p最小等价于使得q最小

否则的话,设p最小时q为x,q最小时p为y

x > q , y > p x>q,y>p x>q,y>p

a b < p x < p q < y q < c d \frac{a}{b}<\frac{p}{x}<\frac{p}{q}<\frac{y}{q}<\frac{c}{d} ba<xp<qp<qy<dc

矛盾,故命题成立。

接着分类讨论:

1:如果

⌊ a b ⌋ + 1 ≤ ⌊ c − 1 d ⌋ \lfloor \frac{a}{b}\rfloor+1\leq \lfloor \frac{c-1}{d}\rfloor ba+1dc1

那么这两个分数之间有一个整数,此时 q q q取到最小值1,根据上述引理等价于p最小

2:如果 a = 0 a=0 a=0,那么相当于只有右边的限制

那么就是

p q < c d \frac{p}{q}<\frac{c}{d} qp<dc

q > d p c q>\frac{dp}{c} q>cdp

取p=1,q= ⌊ d c ⌋ + 1 \lfloor \frac{d}{c} \rfloor+1 cd+1

3:如果 a ≤ b , c ≤ d a\leq b,c\leq d ab,cd,那么我们把所有的分子分母颠倒一下,再把整体式子颠倒一下,就可以转化到 a > b a>b a>b的情况,即
d c < q p < b a \frac{d}{c}<\frac{q}{p}<\frac{b}{a} cd<pq<ab
递归即可

4: a > b a>b a>b
可以把三个分数都减掉 ⌊ a b ⌋ \lfloor \frac{a}{b}\rfloor ba

即为

a m o d    b b < p − q ⌊ a b ⌋ q < c − d ⌊ a b ⌋ d \frac{a\mod b}{b}<\frac{p-q\lfloor \frac{a}{b} \rfloor}{q}< \frac{c-d\lfloor \frac{a}{b}\rfloor}{d} bamodb<qpqba<dcdba

递归即可

复杂度 O ( l o g n ) O(logn) O(logn)

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
void f(LL a,LL b,LL c,LL d,LL &p,LL &q)
{
	if(a/b+1<=(c-1)/d) p=a/b+1,q=1;
	else if(a==0) p=1,q=(d/c+1);
	else if(a<=b&&c<=d) f(d,c,b,a,q,p);
	else f(a%b,b,c-d*(a/b),d,p,q),p+=q*(a/b); 
}
int main()
{
	LL a,b,c,d;
	while(scanf("%lld %lld %lld %lld",&a,&b,&c,&d)!=EOF)
	{
		LL p=0,q=0;
		f(a,b,c,d,p,q);
		printf("%lld/%lld\n",p,q);
	}
	return 0;
}
[COCI2009-2010#1] ALADIN

首先可以把区间离散化,然后用线段树维护区间覆盖,因此,我们只需要要解决形如下列问题即可

∑ i = l r ( ( i − L + 1 ) × A m o d    B ) \sum_{i=l}^r((i-L+1)\times A\mod B) i=lr((iL+1)×AmodB)

∑ i = l r ( ( i − L + 1 ) × A − B ⌊ ( i − L + 1 ) × A B ⌋ ) \sum_{i=l}^r((i-L+1)\times A-B\lfloor \frac{(i-L+1)\times A}{B}\rfloor) i=lr((iL+1)×ABB(iL+1)×A)


F ( n ) = ∑ i = 0 n ( ( i − L + 1 ) × A − B ⌊ ( i − L + 1 ) × A B ⌋ ) F(n)=\sum_{i=0}^n((i-L+1)\times A-B\lfloor \frac{(i-L+1)\times A}{B}\rfloor) F(n)=i=0n((iL+1)×ABB(iL+1)×A)

那么直接用 F ( r ) − F ( l − 1 ) F(r)-F(l-1) F(r)F(l1)即可

前边可以 O ( 1 ) 算 O(1)算 O(1),看后面实际上等价于 B f ( r , A , A − L A , B ) Bf(r,A,A-LA,B) Bf(r,A,ALA,B),不过第二项有可能小于零,可以类似于上面处理的做法做,加上一个值再减掉一个值。

其他的用线段树维护即可

其他题目

CF1098E Fedya the Potter

CF1182F Maximum Sine

CF868G El Toll Caves

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值