引入
类欧几里得算法可以在 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=0∑n⌊cai+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=0n⌊cai+b⌋
首先,先把
a
≥
c
a\geq c
a≥c或
b
≥
c
b\geq c
b≥c的情况通过对
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=0∑n⌊c(c⌊ca⌋+(amodc))i+c⌊cb⌋+(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=0∑n⌊ca⌋i+⌊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) =⌊ca⌋2n(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=0∑n⌊cai+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=0∑nj=0∑⌊cai+b⌋−11
交换求和号:
=
∑
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=0∑m−1i=0∑n[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=0∑m−1i=0∑n[j+1≤cai+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=0∑m−1i=0∑n[cj+c−b−1<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=0∑m−1i=0∑n[⌊acj+c−b−1⌋<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=0∑m−1n−⌊acj+c−b−1⌋
后边是一个递归的形式
= n m − f ( m − 1 , c , c − b − 1 , a ) =nm-f(m-1,c,c-b-1,a) =nm−f(m−1,c,c−b−1,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=0∑n⌊cai+b⌋i
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=0∑n⌊cai+b⌋2
求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)+⌊ca⌋6n(n+1)(2n+1)+⌊cb⌋2n(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=0∑n⌊cai+b⌋i
= ∑ 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=0∑nj=0∑⌊cai+b⌋−1i
设 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=0∑m−1i=0∑n[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=0∑m−1i=0∑n[⌊acj+c−b−1⌋<i]i
设 p = ⌊ c j + c − b − 1 a ⌋ p=\lfloor \frac{cj+c-b-1}{a}\rfloor p=⌊acj+c−b−1⌋
= ∑ j = 0 m − 1 ( p + 1 + n ) ( n − p ) 2 =\sum_{j=0}^{m-1}\frac{(p+1+n)(n-p)}{2} =j=0∑m−12(p+1+n)(n−p)
= 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=0∑m−1n+n2−p2−p
= 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=0∑m−1p−j=0∑m−1p2)
= 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(m−1,c,c−b−1,a)−h(m−1,c,c−b−1,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)
+2⌊cb⌋f(n,amodc,bmodc,c)+2⌊ca⌋g(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)
+⌊ca⌋26n(n+1)(2n+1)+⌊cb⌋2(n+1)+⌊ca⌋⌊cb⌋n(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+c−b−1⌋
为了避免出现求和号相乘的情况,我们换一个形式
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=1∑ni−n
所以
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=0∑n(2j=1∑⌊cai+b⌋j−⌊cai+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=0∑nj=1∑⌊cai+b⌋j−f(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=0∑nj=0∑⌊cai+b⌋−1(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=0∑m−1(j+1)i=0∑n[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=0∑m−1(j+1)i=0∑n[⌊acj+c−b−1⌋<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=0∑m−1(j+1)i=0∑n[p<i]
= ∑ j = 0 m − 1 ( j + 1 ) ( n − p ) =\sum_{j=0}^{m-1}(j+1)(n-p) =j=0∑m−1(j+1)(n−p)
= ∑ j = 0 m − 1 j n + n − j p − p =\sum_{j=0}^{m-1}jn+n-jp-p =j=0∑m−1jn+n−jp−p
= 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=0∑m−1ip−i=0∑p
= 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(m−1,c,c−b−1,a)−f(m−1,c,c−b−1,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+by≤c
所以
y ≤ ⌊ c − a x b ⌋ y\leq \lfloor \frac{c-ax}{b}\rfloor y≤⌊bc−ax⌋
那么对于一个固定的x,合法的y的个数为 ⌊ c − a x b ⌋ + 1 \lfloor \frac{c-ax}{b}\rfloor+1 ⌊bc−ax⌋+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=0∑⌊ac⌋⌊bc−ax⌋+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=0∑⌊ac⌋⌊bc+(b−a)x⌋−x+1
前面的直接用类欧,后边的可以直接算出来。
因为原题的限制对 a , b a,b a,b是对称的,因此为了保证 b − a ≥ 0 b-a\geq0 b−a≥0,如果 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=1−2(nmod2)=1−2(n−2⌊2n⌋)=1−2n+4⌊2n⌋
所以原式为
∑ 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=1∑n1−2⌊ix⌋+4⌊2⌊ix⌋⌋=n−2i=1∑n⌊ix⌋+4i=1∑n⌊2ix⌋
设
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=1∑n⌊cax+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) n−2f(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=1∑n⌊pi⌋
= ∑ i = 1 n ⌊ p i − q i + q i ⌋ =\sum_{i=1}^n\lfloor pi-qi+qi\rfloor =i=1∑n⌊pi−qi+qi⌋
= ∑ i = 1 n ⌊ ( p − q ) i ⌋ + q i =\sum_{i=1}^n\lfloor (p-q)i\rfloor+qi =i=1∑n⌊(p−q)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=1∑n⌊(cax+b−q)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,b−cq,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=1∑nj=1∑⌊pn⌋[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=1∑nj=1∑⌊pn⌋[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=1∑⌊pn⌋i=1∑n[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=1∑⌊pn⌋n−⌊pj⌋
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=1∑⌊pn⌋n−⌊cax+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=1∑⌊pn⌋n−⌊ax+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=1∑⌊pn⌋n−⌊(ax+b)(ax−b)c(ax−b)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)=⌊pn⌋n−j=1∑⌊pn⌋⌊a2x2+b2acx−bc)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)=⌊pn⌋n−j=1∑⌊pn⌋⌊a2r+b2acx−bc)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)=⌊pn⌋n−f(⌊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⌋+1≤⌊dc−1⌋
那么这两个分数之间有一个整数,此时 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
a≤b,c≤d,那么我们把所有的分子分母颠倒一下,再把整体式子颠倒一下,就可以转化到
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<qp−q⌊ba⌋<dc−d⌊ba⌋
递归即可
复杂度 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=l∑r((i−L+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=l∑r((i−L+1)×A−B⌊B(i−L+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=0∑n((i−L+1)×A−B⌊B(i−L+1)×A⌋)
那么直接用 F ( r ) − F ( l − 1 ) F(r)-F(l-1) F(r)−F(l−1)即可
前边可以 O ( 1 ) 算 O(1)算 O(1)算,看后面实际上等价于 B f ( r , A , A − L A , B ) Bf(r,A,A-LA,B) Bf(r,A,A−LA,B),不过第二项有可能小于零,可以类似于上面处理的做法做,加上一个值再减掉一个值。
其他的用线段树维护即可