【算法】 类欧几里德算法

参考自:点击打开链接

模板题链接

点击打开链接

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

几个等式关系

  • a ≤ ⌊ b c ⌋    ⟺    a c ≤ b a\le \lfloor \frac{b}{c}\rfloor \iff ac \le b acbacb
  • a < ⌈ b c ⌉    ⟺    a c < b a<\lceil \frac{b}{c}\rceil \iff aca<cbac<b
  • a ≥ ⌈ b c ⌉    ⟺    a c ≥ b a\ge \lceil \frac{b}{c}\rceil \iff ac\ge b acbacb
  • a > ⌊ b c ⌋    ⟺    a c > b a> \lfloor \frac{b}{c}\rfloor \iff ac>b a>cbac>b
  • ⌊ b c ⌋    ⟺    ⌈ b − c + 1 c ⌉ \lfloor \frac{b}{c}\rfloor \iff\lceil \frac{b-c+1}{c}\rceil cbcbc+1
  • ⌈ b c ⌉    ⟺    ⌊ b + c − 1 c ⌋ \lceil \frac{b}{c} \rceil \iff \lfloor \frac{b+c-1}{c}\rfloor cbcb+c1

f f f 函数

这个函数有几何意义,即 f ( x ) = a x + b c f(x)=\frac{ax+b}{c} f(x)=cax+b 的函数下方正整点的个数
下面考虑代数的解法

考虑将 a ≥ c a\ge c ac b ≥ c b\ge c bc 的情况变成 a < c aa<c b < c bb<c 的情况

f ( a , b , c , n ) = ∑ i = 1 n ⌊ a i + b c ⌋ = ∑ i = 1 n ⌊ ( a % c ) ∗ i + ( b % c ) ∗ i c ⌋ + ⌊ a c ⌋ ∗ i + ⌊ b c ⌋ = ⌊ a c ⌋ ∗ n ∗ ( n + 1 ) 2 + ⌊ b c ⌋ ∗ ( n + 1 ) + ∑ i = 1 n ⌊ ( a % c ) ∗ i + ( b % c ) ∗ i c ⌋ = ⌊ a c ⌋ ∗ n ∗ ( n + 1 ) 2 + ⌊ b c ⌋ ∗ ( n + 1 ) + f ( a % c , b % c , c , n ) f(a,b,c,n)\\=\sum_{i=1}^{n}\lfloor\frac{ai+b}{c}\rfloor \\ =\sum_{i=1}^{n}\lfloor \frac{(a\%c)*i+(b\%c)*i}{c} \rfloor+\lfloor \frac{a}{c}\rfloor*i+\lfloor\frac{b}{c}\rfloor \\ =\lfloor \frac{a}{c}\rfloor*\frac{n*(n+1)}{2}+\lfloor\frac{b}{c}\rfloor*(n+1)+\sum_{i=1}^{n}\lfloor \frac{(a\%c)*i+(b\%c)*i}{c}\rfloor \\ =\lfloor \frac{a}{c}\rfloor*\frac{n*(n+1)}{2}+\lfloor\frac{b}{c}\rfloor*(n+1)+f(a\%c,b\%c,c,n) f(a,b,c,n)=i=1ncai+b=i=1nc(a%c)i+(b%c)i+cai+cb=ca2n(n+1)+cb(n+1)+i=1nc(a%c)i+(b%c)i=ca2n(n+1)+cb(n+1)+f(a%c,b%c,c,n)

现在只需要考虑 a < c aa<c b < c bb<c 的情况如何转移到上面的情况

f ( a , b , c , n ) ( a < c , b < c ) = ∑ i = 1 n ⌊ a i + b c ⌋ = ∑ i = 1 n ∑ j = 1 ⌊ a n + b c ⌋ [ j ≤ a i + b c ] f(a,b,c,n)(af(a,b,c,n)(a<c,b<c)=i=1ncai+b=i=1nj=1can+b[jcai+b]
⌊ a n + b c ⌋ = m \lfloor\frac{an+b}{c}\rfloor=m can+b=m
考虑变换 j ≤ a i + b c j\le \frac{ai+b}{c} jcai+b 的形式,使其分离出单独的 i i i
j ≤ a i + b c    ⟺    j c ≤ a i + b    ⟺    j c − b < = a i    ⟺    ⌊ j c − b − 1 a ⌋ < i j\le \frac{ai+b}{c}\iff jc\le ai+b\iff jc-b<=ai\iff \lfloor\frac{jc-b-1}{a}\rfloorjcai+bjcai+bjcb<=aiajcb1<i
带入原式得:
f ( a , b , c , n ) ( a < c , b < c ) = ∑ i = 1 n ∑ j = 1 m [ ⌊ j c − b − 1 a ⌋ < i ] f(a,b,c,n)(af(a,b,c,n)(a<c,b<c)=i=1nj=1m[⌊ajcb1<i]
交换循环顺序,
= ∑ j = 1 m ∑ i = 1 n [ ⌊ j c − b − 1 a ⌋ < i ] = ∑ j = 1 m n − ⌊ j c − b − 1 a ⌋ = m n − ∑ j = 1 m ⌊ j c − b − 1 a ⌋ = m n − ∑ j = 0 m − 1 ⌊ j c + c − b − 1 a ⌋ =\sum_{j=1}^{m}\sum_{i=1}^{n}[\lfloor\frac{jc-b-1}{a}\rfloor=j=1mi=1n[⌊ajcb1<i]=j=1mnajcb1=mnj=1majcb1=mnj=0m1ajc+cb1
后面的形式和是当前问题的子问题考虑递归下去求解
= m n − f ( c , c − b − 1 , a , m − 1 ) =mn-f(c,c-b-1,a,m-1) =mnf(c,cb1,a,m1)

考虑分析时间复杂度
对与 a ≥ c a\ge c ac b ≥ c b\ge c bc 的情况的时间复杂度与欧几里得算法一样,是 l o g log log 级别的
对于 a < c aa<c b < c bb<c 的情况,必定会转变到 a ≥ c a\ge c ac b ≥ c b\ge c bc 的情况,所以也是 l o g log log 级别的
整体的时间复杂度是 l o g log log
之后 g , h g,h g,h 函数的时间复杂度分析相同

g g g 函数

考虑将 a ≥ c a\ge c ac b ≥ c b\ge c bc 的情况变成 a < c aa<c b < c bb<c 的情况

g ( a , b , c , n ) = ∑ i = 1 n i ⌊ a i + b c ⌋ = ∑ i = 1 n i ⌊ ( a % c ) ∗ i + ( b % c ) c ⌋ + i 2 ∗ ⌊ a c ⌋ + i ∗ ⌊ b c ⌋ = n ( n + 1 ) ( 2 n + 1 ) 6 ∗ ⌊ a c ⌋ + n ( n + 1 ) 2 ∗ ⌊ b c ⌋ + ∑ i = 1 n i ⌊ ( a % c ) ∗ i + ( b % c ) c ⌋ = n ( n + 1 ) ( 2 n + 1 ) 6 ∗ ⌊ a c ⌋ + g ( a % c , b % c , c , n ) g(a,b,c,n) \\=\sum_{i=1}^{n}i\lfloor\frac{ai+b}{c}\rfloor \\=\sum_{i=1}^{n}i\lfloor\frac{(a\%c)*i+(b\%c)}{c}\rfloor+i^2*\lfloor \frac{a}{c}\rfloor+i*\lfloor \frac{b}{c}\rfloor \\=\frac{n(n+1)(2n+1)}{6}*\lfloor\frac{a}{c}\rfloor+\frac{n(n+1)}{2}*\lfloor\frac{b}{c}\rfloor +\sum_{i=1}^{n}i\lfloor\frac{(a\%c)*i+(b\%c)}{c}\rfloor \\=\frac{n(n+1)(2n+1)}{6}*\lfloor\frac{a}{c}\rfloor+g(a\%c,b\%c,c,n) g(a,b,c,n)=i=1nicai+b=i=1nic(a%c)i+(b%c)+i2ca+icb=6n(n+1)(2n+1)ca+2n(n+1)cb+i=1nic(a%c)i+(b%c)=6n(n+1)(2n+1)ca+g(a%c,b%c,c,n)

考虑 a < c , b < c aa<c,b<c 的情况

考虑套用 f f f 的方法,
g ( a , b , c , n ) = ∑ i = 1 n i ⌊ a i + b c ⌋ = ∑ j = 0 m − 1 ∑ i = 0 n [ i > ⌊ c j + c − b − 1 a ⌋ ] ∗ i g(a,b,c,n) \\=\sum_{i=1}^{n}i\lfloor\frac{ai+b}{c}\rfloor \\=\sum_{j=0}^{m-1}\sum_{i=0}^{n}[i>\lfloor \frac{cj+c-b-1}{a}\rfloor]*i g(a,b,c,n)=i=1nicai+b=j=0m1i=0n[i>acj+cb1⌋]i
⌊ c j + c − b − 1 a ⌋ = t \lfloor \frac{cj+c-b-1}{a}\rfloor=t acj+cb1=t
= ∑ j = 0 m − 1 ∑ i = t + 1 n i = ∑ j = 0 m − 1 ( t + 1 + n ) ∗ ( n − t ) 2 = 1 2 ∗ ∑ j = 0 m − 1 n + n 2 − t − t 2 = 1 2 m n ( n + 1 ) − 1 2 ∗ ∑ i = 0 m − 1 t 2 − 1 2 ∗ ∑ i = 0 m − 1 t = 1 2 m n ( n + 1 ) − 1 2 ∗ h ( c , c − b − 1 , a , m − 1 ) − 1 2 ∗ f ( c , c − b − 1 , a , m − 1 ) \\=\sum_{j=0}^{m-1}\sum_{i=t+1}^{n}i \\=\sum_{j=0}^{m-1}\frac{(t+1+n)*(n-t)}{2} \\=\frac{1}{2}*\sum_{j=0}^{m-1}n+n^2-t-t^2 \\=\frac{1}{2}mn(n+1)-\frac{1}{2}*\sum_{i=0}^{m-1}t^2-\frac{1}{2}*\sum_{i=0}^{m-1}t \\=\frac{1}{2}mn(n+1)-\frac{1}{2}*h(c,c-b-1,a,m-1)-\frac{1}{2}*f(c,c-b-1,a,m-1) =j=0m1i=t+1ni=j=0m12(t+1+n)(nt)=21j=0m1n+n2tt2=21mn(n+1)21i=0m1t221i=0m1t=21mn(n+1)21h(c,cb1,a,m1)21f(c,cb1,a,m1)

h h h 函数

考虑将 a ≥ c a\ge c ac b ≥ c b\ge c bc 的情况变成 a < c aa<c b < c bb<c 的情况

h ( a , b , c , n ) = ∑ i = 0 n ⌊ a i + b c ⌋ 2 = ∑ i = 0 n ( ⌊ ( a % c ) i + ( b % c ) c ⌋ + ⌊ a c ⌋ ∗ i + ⌊ b c ⌋ ) 2 h(a,b,c,n) \\=\sum_{i=0}^{n}\lfloor\frac{ai+b}{c}\rfloor^2 \\=\sum_{i=0}^{n}(\lfloor\frac{(a\%c)i+(b\%c)}{c}\rfloor+\lfloor\frac{a}{c}\rfloor *i+\lfloor\frac{b}{c}\rfloor)^2 h(a,b,c,n)=i=0ncai+b2=i=0n(⌊c(a%c)i+(b%c)+cai+cb)2
化简可得
= ⌊ a c ⌋ 2 ∗ n ( n + 1 ) ( 2 n + 1 ) 6 + ⌊ b c ⌋ 2 ( n + 1 ) + ⌊ b c ⌋ ⌊ a c ⌋ ∗ n ( n + 1 ) + h ( a % c , b % c , c , n ) + 2 ⌊ b c ⌋ ∗ f ( a % c , b % c , c , n ) + 2 ⌊ a c ⌋ ∗ g ( a % c , b % c , c , n ) \\=\lfloor\frac{a}{c}\rfloor^2*\frac{n(n+1)(2n+1)}{6}+\lfloor\frac{b}{c}\rfloor^2(n+1)+\lfloor\frac{b}{c}\rfloor\lfloor\frac{a}{c}\rfloor*n(n+1)+h(a\%c,b\%c,c,n)+2\lfloor\frac{b}{c}\rfloor*f(a\%c,b\%c,c,n)+2\lfloor\frac{a}{c}\rfloor*g(a\%c,b\%c,c,n) =ca26n(n+1)(2n+1)+cb2(n+1)+cbcan(n+1)+h(a%c,b%c,c,n)+2cbf(a%c,b%c,c,n)+2cag(a%c,b%c,c,n)

考虑 a < c , b < c aa<c,b<c 的情况

平方有一个巧妙地变形方法:
t 2 = 2 ∗ t ( t + 1 ) 2 − t = 2 ∗ ∑ i = 1 t i − t t^2=2*\frac{t(t+1)}{2}-t=2*\sum_{i=1}^{t}i-t t2=22t(t+1)t=2i=1tit
带入式子可得:
h ( a , b , c , n ) = ∑ i = 0 n ⌊ a i + b c ⌋ 2 = 2 ∗ ∑ i = 0 n ∑ j = 1 ⌊ a i + b c ⌋ j − f ( a , b , c , n ) h(a,b,c,n) \\=\sum_{i=0}^{n}\lfloor\frac{ai+b}{c}\rfloor^2 \\=2*\sum_{i=0}^{n}\sum_{j=1}^{\lfloor\frac{ai+b}{c}\rfloor}j-f(a,b,c,n) h(a,b,c,n)=i=0ncai+b2=2i=0nj=1cai+bjf(a,b,c,n)
m = ⌊ a n + b c ⌋ , t = ⌊ a i + b c ⌋ m=\lfloor\frac{an+b}{c}\rfloor,t=\lfloor\frac{ai+b}{c}\rfloor m=can+bt=cai+b
所以 ∑ i = 0 n ∑ j = 1 t j = ∑ i = 0 n ∑ j = 0 t − 1 j + 1 = ∑ j = 0 m − 1 ( j + 1 ) ∗ ∑ i = 1 n [ j < t ] = ∑ j = 0 m − 1 ( j + 1 ) ∗ ∑ i = 1 n [ i > ⌊ j c + c − b − 1 a ⌋ ] \sum_{i=0}^{n}\sum_{j=1}^{t}j \\=\sum_{i=0}^{n}\sum_{j=0}^{t-1}j+1 \\=\sum_{j=0}^{m-1}(j+1)*\sum_{i=1}^{n}[j\lfloor\frac{jc+c-b-1}{a}\rfloor] i=0nj=1tj=i=0nj=0t1j+1=j=0m1(j+1)i=1n[j<t]=j=0m1(j+1)i=1n[i>ajc+cb1⌋]
所以
f ( a , b , c , n ) = n m ( m + 1 ) − 2 h ( c , c − b − 1 , a , m − 1 ) − 2 f ( c , c − b − 1 , a , m − 1 ) − f ( a , b , c , n ) f(a,b,c,n)=nm(m+1)-2h(c,c-b-1,a,m-1)-2f(c,c-b-1,a,m-1)-f(a,b,c,n) f(a,b,c,n)=nm(m+1)2h(c,cb1,a,m1)2f(c,cb1,a,m1)f(a,b,c,n)

考虑计算时会重复计算许多相同的量,可以用结构体记录相同 a , b , c , n a,b,c,n a,b,c,n f , g , h f,g,h f,g,h,因为 f , g , h f,g,h f,g,h 同步计算时调用的函数相同,所以时间复杂度 O ( l o g n ) O(logn) O(logn)

#include 
#define int long long
using namespace std;
const int P(998244353);
struct ecu{ int f,g,h;};
int iv2=499122177,iv6=166374059;
inline int read(){
	int FF=0,RR=1;
	char ch=getchar();
	for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
	for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
	return FF*RR;
}
int sum(int n){ return n*(n+1)%P*iv2%P;}
int sum2(int n){ return n*(n+1)%P*(2*n+1)%P*iv6%P;}
ecu solve(int a,int b,int c,int n){
	ecu ret;
	if(!a){
		ret.f=(n+1)*(b/c)%P;
		ret.g=sum(n)*(b/c)%P;
		ret.h=(n+1)*(b/c)%P*(b/c)%P;
//		cout<
		return ret;
	}
	if(a>=c||b>=c){
		ecu t=solve(a%c,b%c,c,n);
		ret.f=(t.f+a/c*sum(n)%P+b/c*(n+1)%P)%P;
		ret.g=(t.g+a/c*sum2(n)%P+b/c*sum(n)%P)%P;
		ret.h=(t.h+2*(b/c)*t.f%P+2*(a/c)*t.g%P+(a/c)*(a/c)%P*sum2(n)%P+(b/c)*(b/c)%P*(n+1)%P+(a/c)*(b/c)%P*n%P*(n+1)%P)%P;
		return ret;
	}
	int m=(a*n+b)/c;
	ecu t=solve(c,c-b-1,a,m-1);
	ret.f=(m*n%P-t.f+P)%P;
	ret.g=(m*n%P*(n+1)%P-t.h-t.f+2*P)%P*iv2%P;
	ret.h=((n*m%P*(m+1)%P-2*t.g%P-2*t.f%P-ret.f)%P+P)%P;
	return ret;
}
void work(){
	int n=read(),a=read(),b=read(),c=read();
	ecu ans=solve(a,b,c,n);
	printf("%lld %lld %lld\n",ans.f,ans.h,ans.g);
}
signed main(){
	int T=read();
	while(T--) work();
	return 0;
}

你可能感兴趣的:(算法,算法)