【模板】类欧几里得


模板
传送门

由于太懒以下直接用 a / b 表 示 ⌊ a b ⌋ a/b表示\lfloor \frac a b\rfloor a/bba
如果有乘除叠一起会单独打括号区分乘除的地方

1 、 f : 1、f: 1f

f ( a , b , c , n ) = ∑ i = 0 n ( a i + b ) / c f(a,b,c,n)=\sum_{i=0}^n(ai+b)/c f(a,b,c,n)=i=0n(ai+b)/c
a = 0 a=0 a=0
f = ( n + 1 ) ( b / c ) f=(n+1)(b/c) f=(n+1)(b/c)
否则若有 a ≥ c ∣ ∣ b ≥ c a\geq c ||b\geq c acbc
f = ∑ i = 0 n ( i a % c + b % c ) / c + i ( a / c ) + ( b / c ) f=\sum_{i=0}^{n}(ia\%c+b\%c)/c+i(a/c)+(b/c) f=i=0n(ia%c+b%c)/c+i(a/c)+(b/c)
= f ( a % c , b % c , c , n ) + n ∗ ( n + 1 ) / 2 ∗ ( a / c ) + ( n + 1 ) ( b / c ) =f(a\%c,b\%c,c,n)+n*(n+1)/2*(a/c)+(n+1)(b/c) =f(a%c,b%c,c,n)+n(n+1)/2(a/c)+(n+1)(b/c)
a < c a<c a<c b < c b<c b<c
m = ( a n + b ) / c m=(an+b)/c m=(an+b)/c
f = ∑ i = 0 n ∑ j = 1 m [ j ≤ ( a i + b ) / c ] f=\sum_{i=0}^n\sum_{j=1}^{m}[j\le(ai+b)/c] f=i=0nj=1m[j(ai+b)/c]
f = ∑ i = 0 n ∑ j = 0 m − 1 [ j + 1 < ( a i + b + 1 ) / c ] f=\sum_{i=0}^n\sum_{j=0}^{m-1}[j+1<(ai+b+1)/c] f=i=0nj=0m1[j+1<(ai+b+1)/c]
= ∑ i = 0 n ∑ j = 0 m − 1 [ i > ( j c + c − b − 1 ) / a ] =\sum_{i=0}^n\sum_{j=0}^{m-1}[i>(jc+c-b-1)/a] =i=0nj=0m1[i>(jc+cb1)/a]
= ∑ j = 0 m − 1 ∑ i = 0 n [ i > ( j c + c − b − 1 ) / a ] =\sum_{j=0}^{m-1}\sum_{i=0}^n[i>(jc+c-b-1)/a] =j=0m1i=0n[i>(jc+cb1)/a]
= ∑ j = 0 m − 1 n − ( j c + c − b − 1 ) / a =\sum_{j=0}^{m-1}n-(jc+c-b-1)/a =j=0m1n(jc+cb1)/a
= n m − f ( c , c − b − 1 , a , m − 1 ) =nm-f(c,c-b-1,a,m-1) =nmf(c,cb1,a,m1)

显然复杂度为 O ( l o g n ) O(logn) O(logn)

2 : g , h 2:g,h 2:g,h
g ( a , b , c , n ) = ∑ i = 0 n ( ( a i + b ) / c ) 2 g(a,b,c,n)=\sum_{i=0}^n((ai+b)/c)^2 g(a,b,c,n)=i=0n((ai+b)/c)2
h ( a , b , c , n ) = ∑ i = 0 n i ( ( a i + b ) / c ) h(a,b,c,n)=\sum_{i=0}^ni((ai+b)/c) h(a,b,c,n)=i=0ni((ai+b)/c)
首先类似
a = 0 a=0 a=0
g = ( n + 1 ) ( b / c ) 2 , h = n ∗ ( n + 1 ) / 2 ∗ ( b / c ) g=(n+1)(b/c)^2,h=n*(n+1)/2*(b/c) g=(n+1)(b/c)2,h=n(n+1)/2(b/c)

a ≥ c ∣ ∣ b ≥ c a\geq c||b\geq c acbc
类似之前 f f f
拆开得到
g = g ( a % c , b % c , c , n ) + 2 ∗ ( a / c ) ∗ h ( a % c , b % c , c , n ) + 2 ∗ ( b / c ) ∗ f ( a % c , b % c , c , n ) + ( a / c ) ∗ ( b / c ) ∗ n ∗ ( n + 1 ) + n ∗ ( n + 1 ) ∗ ( 2 n + 1 ) / 6 ∗ ( a / c ) 2 + ( n + 1 ) ∗ ( b / c ) 2 g=g(a\%c,b\%c,c,n)+2*(a/c)*h(a\%c,b\%c,c,n)+2*(b/c)*f(a\%c,b\%c,c,n)\\+(a/c)*(b/c)*n*(n+1)+n*(n+1)*(2n+1)/6*(a/c)^2+(n+1)*(b/c)^2 g=g(a%c,b%c,c,n)+2(a/c)h(a%c,b%c,c,n)+2(b/c)f(a%c,b%c,c,n)+(a/c)(b/c)n(n+1)+n(n+1)(2n+1)/6(a/c)2+(n+1)(b/c)2
h = h ( a % c , b % c , c , n ) + n ∗ ( n + 1 ) ∗ ( 2 n + 1 ) / 6 ∗ ( a / c ) + n ∗ ( n + 1 ) / 2 ∗ ( b / c ) h=h(a\%c,b\%c,c,n)+n*(n+1)*(2n+1)/6*(a/c)+n*(n+1)/2*(b/c) h=h(a%c,b%c,c,n)+n(n+1)(2n+1)/6(a/c)+n(n+1)/2(b/c)

a < c a<c a<c b < c b<c b<c
m = ( a n + b ) / c m=(an+b)/c m=(an+b)/c
g = ∑ i = 0 n ( ( a i + b ) / c ) 2 g=\sum_{i=0}^n((ai+b)/c)^2 g=i=0n((ai+b)/c)2
= 2 ∗ ∑ i = 0 n ∑ j = 1 ( a i + b ) / c j − ∑ i = 0 n ( a i + b ) / c = − f ( a , b , c , n ) + 2 ∑ i = 0 n ∑ j = 0 m − 1 ( j + 1 ) [ j c + c < a i + b + 1 ] = − f + 2 ∑ j = 0 m − 1 ( j + 1 ) [ i > ( j c + c − b − 1 ) / a ] = − f + 2 ∑ j = 0 m − 1 ( j + 1 ) ( n − ( j c + c − b − 1 ) / a ) = − f ( a , b , c , n ) + m ( m + 1 ) n − 2 f ( c , c − b − 1 , a , m − 1 ) − 2 h ( c , c − b − 1 , a , m − 1 ) =2*\sum_{i=0}^n\sum_{j=1}^{(ai+b)/c}j-\sum_{i=0}^n(ai+b)/c\\ =-f(a,b,c,n)+2\sum_{i=0}^n\sum_{j=0}^{m-1}(j+1)[jc+c<ai+b+1]\\ =-f+2\sum_{j=0}^{m-1}(j+1)[i>(jc+c-b-1)/a]\\ =-f+2\sum_{j=0}^{m-1}(j+1)(n-(jc+c-b-1)/a)\\ =-f(a,b,c,n)+m(m+1)n-2f(c,c-b-1,a,m-1)-2h(c,c-b-1,a,m-1) =2i=0nj=1(ai+b)/cji=0n(ai+b)/c=f(a,b,c,n)+2i=0nj=0m1(j+1)[jc+c<ai+b+1]=f+2j=0m1(j+1)[i>(jc+cb1)/a]=f+2j=0m1(j+1)(n(jc+cb1)/a)=f(a,b,c,n)+m(m+1)n2f(c,cb1,a,m1)2h(c,cb1,a,m1)

h = ∑ i = 0 n i ( ( a i + b ) / c ) = ∑ i = 0 n i ∑ j = 0 m − 1 [ i > ( j c + c − b − 1 ) / a ] = ∑ j = 0 m − 1 ∑ i = 0 n i [ i > ( j c + c − b − 1 ) / a ] = m ∗ n ∗ ( n + 1 ) / 2 − ∑ j = 0 m − 1 ∑ i = 0 n i [ i ≤ ( j c + c − b − 1 ) / a ] = m ∗ n ∗ ( n + 1 ) / 2 − ∑ j = 0 m − 1 ∑ i = 0 ( j c + c − b − 1 ) / a i = m ∗ n ∗ ( n + 1 ) / 2 − ∑ j = 0 m − 1 ( ( j c + c − b − 1 ) / a ) ∗ ( ( j c + c − b − 1 ) / a + 1 ) / 2 = 1 2 ( m ∗ n ∗ ( n + 1 ) − ∑ i = 0 m − 1 ( ( j c + c − b − 1 ) / a ) 2 − ∑ i = 0 m − 1 ( ( j c + c − b − 1 ) / a ) ) = 1 2 ( m ∗ n ∗ ( n + 1 ) − f ( c , c − b − 1 , a , m − 1 ) − g ( c , c − b − 1 , a , m − 1 ) ) h=\sum_{i=0}^ni((ai+b)/c)\\ =\sum_{i=0}^ni\sum_{j=0}^{m-1}[i>(jc+c-b-1)/a]\\ =\sum_{j=0}^{m-1}\sum_{i=0}^ni[i>(jc+c-b-1)/a]\\ =m*n*(n+1)/2-\sum_{j=0}^{m-1}\sum_{i=0}^ni[i\le(jc+c-b-1)/a]\\ =m*n*(n+1)/2-\sum_{j=0}^{m-1}\sum_{i=0}^{(jc+c-b-1)/a}i\\ =m*n*(n+1)/2-\sum_{j=0}^{m-1}((jc+c-b-1)/a)*((jc+c-b-1)/a+1)/2\\ =\frac 1 2(m*n*(n+1)-\sum_{i=0}^{m-1}((jc+c-b-1)/a)^2-\sum_{i=0}^{m-1}((jc+c-b-1)/a))\\ =\frac 1 2(m*n*(n+1)-f(c,c-b-1,a,m-1)-g(c,c-b-1,a,m-1)) h=i=0ni((ai+b)/c)=i=0nij=0m1[i>(jc+cb1)/a]=j=0m1i=0ni[i>(jc+cb1)/a]=mn(n+1)/2j=0m1i=0ni[i(jc+cb1)/a]=mn(n+1)/2j=0m1i=0(jc+cb1)/ai=mn(n+1)/2j=0m1((jc+cb1)/a)((jc+cb1)/a+1)/2=21(mn(n+1)i=0m1((jc+cb1)/a)2i=0m1((jc+cb1)/a))=21(mn(n+1)f(c,cb1,a,m1)g(c,cb1,a,m1))

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


万能欧几里得
传送门
∑ i = 1 l A i B ( p i + r ) / q \sum_{i=1}^lA^iB^{(pi+r)/q} i=1lAiB(pi+r)/q
考虑这样一个操作
维护一个三元组 a , b , s a,b,s a,b,s
考虑一条线段 y = ( p x + r ) / q y=(px+r)/q y=(px+r)/q
( 0 , L ] (0,L] (0,L]内从左往右走
每当线段碰到 x = c x=c x=c时令 a = a ∗ A a=a*A a=aA
每当碰到 y = c y=c y=c时令 b = b ∗ B b=b*B b=bB
对于整点先进行 y = c y=c y=c再进行 x = c x=c x=c
每次操作后令 n e w   s = s + A ∗ B new \ s=s+A*B new s=s+AB

显然这和原来求得东西等价
观察到这是一个线性变换,拥有结合律

万能欧几里得能利用压缩信息在 O ( l o g T ( n ) ) O(logT(n)) O(logT(n))的时间求出这个东西
考虑当 r ≥ q r\geq q rq时令 r = r % q r=r\%q r=r%q不会对操作序列产生影响
只是初始的 b b b会变成 b r / q b^{r/q} br/q,先做即可
设函数为 f ( p , q , r , l , a , b ) f(p,q,r,l,a,b) f(p,q,r,l,a,b)

p ≥ q p\geq q pq
k = ( p / q ) k=(p/q) k=(p/q)
那么考虑线段为 y = k x + ( ( p % q ) x + r ) / q y=kx+((p\%q)x+r)/q y=kx+((p%q)x+r)/q
那么每次 x x x加一前必定会至少有 k k k y y y的变化
于是可以直接递归 f ( p % q , q , r , l , b k ∗ a , b ) f(p\%q,q,r,l,b^{k}*a,b) f(p%q,q,r,l,bka,b)

否则考虑可以翻转坐标轴,将 x , y x,y x,y反过来
翻转后的函数就是反函数
x = ( q y − r ) / p x=(qy-r)/p x=(qyr)/p
但是这时候如果按照原来的在整点时候的计算顺序就反了
于是考虑变成 x = ( q y − r − 1 ) / p x=(qy-r-1)/p x=(qyr1)/p强制先计算 x x x
k = ( p l + r ) / q k=(pl+r)/q k=(pl+r)/q
考虑翻转后求 y ∈ ( 1 , k ] y\in(1,k] y(1,k]范围内的
那显然要先把前面没计算的部分求了
就是 a ( q − r − 1 ) / p ∗ b a^{(q-r-1)/p}*b a(qr1)/pb
考虑把 y ∈ ( 1 , k ] → y ∈ ( 0 , k − 1 ] y\in(1,k]\rightarrow y\in(0,k-1] y(1,k]y(0,k1]
那么函数就变成 x = ( q y + q − r − 1 ) / p x=(qy+q-r-1)/p x=(qy+qr1)/p
于是递归 f ( q , p , q − r − l , k − 1 , b , a ) f(q,p,q-r-l,k-1,b,a) f(q,p,qrl,k1,b,a)
但是 k k k之后可能还有一些 x x x没被计算到
个数是 l − ( k q − r − 1 ) / p l-(kq-r-1)/p l(kqr1)/p
于是在后面乘上一个 a l − ( k q − r − 1 ) / p a^{l-(kq-r-1)/p} al(kqr1)/p即可

复杂度应该是 O ( n 3 l o g ) O(n^3log) O(n3log)

#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re register
#define pb push_back
#define pii pair<int,int>
#define ll long long
#define fi first
#define se second
#define bg begin
cs int RLEN=1<<20|1;
inline char gc(){
    static char ibuf[RLEN],*ib,*ob;
    (ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ib==ob)?EOF:*ib++;
}
inline int read(){
    char ch=gc();
    int res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
inline ll readll(){
    char ch=gc();
    ll res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
inline int readstring(char *s){
	int top=0;char ch=gc();
	while(isspace(ch))ch=gc();
	while(!isspace(ch)&&ch!=EOF)s[++top]=ch,ch=gc();
	return top;
}
template<typename tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<typename tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
cs int mod=998244353;
inline int add(int a,int b){return (a+=b)>=mod?(a-mod):a;}
inline int dec(int a,int b){a-=b;return a+(a>>31&mod);}
inline int mul(int a,int b){static ll r;r=1ll*a*b;return (r>=mod)?(r%mod):r;}
inline void Add(int &a,int b){(a+=b)>=mod?(a-=mod):0;}
inline void Dec(int &a,int b){a-=b,a+=a>>31&mod;}
inline void Mul(int &a,int b){static ll r;r=1ll*a*b;a=(r>=mod)?(r%mod):r;}
inline int ksm(int a,int b,int res=1){if(a==0&&b==0)return 0;for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
inline int Inv(int x){return ksm(x,mod-2);}
inline int fix(ll x){return x%=mod,(x<0)?x+mod:x;}
int n;
struct mat{
	int a[21][21];
	mat(){memset(a,0,sizeof(a));}
	friend inline mat operator *(cs mat &a,cs mat &b){
		mat c;
		for(int i=0;i<n;i++)
		for(int k=0;k<n;k++)
		for(int j=0;j<n;j++)
		Add(c.a[i][j],mul(a.a[i][k],b.a[k][j]));
		return c;
	}
	friend inline mat operator +(cs mat &a,cs mat &b){
		mat c;
		for(int i=0;i<n;i++)
		for(int j=0;j<n;j++)
		c.a[i][j]=add(a.a[i][j],b.a[i][j]);
		return c;
	}
}I,O,A,B;
struct node{
	mat a,b,s;
	node(mat _a,mat _b,mat _c):a(_a),b(_b),s(_c){}
	friend inline node operator *(cs node &x,cs node &y){
		return node(x.a*y.a,x.b*y.b,x.s+x.a*y.s*x.b);
	}
	friend inline node operator ^(node x,ll b){
		node res(I,I,O);
		for(;b;b>>=1,x=x*x)if(b&1)res=res*x;
		return res;
	}
};
node solve(ll p,ll q,ll r,ll l,cs node &a,cs node &b){
	if(l==0)return node(I,I,O);
	r%=q;
	if(p>=q)return solve(p%q,q,r,l,(b^(p/q))*a,b);
	ll k=((long double)p*l+r)/q;
	if(k==0)return a^l;
	ll v=((long double)k*q-r-1)/p;
	v=l-v;
	return (a^((q-r-1)/p))*b*solve(q,p,q-r-1,k-1,b,a)*(a^v);
}
ll p,q,r,l;
int main(){
	#ifdef Stargazer
	freopen("lx.in","r",stdin);
	#endif
	p=readll(),q=readll(),r=readll(),l=readll(),n=read();
	for(int i=0;i<n;i++)
	for(int j=0;j<n;j++)A.a[i][j]=read();
	for(int i=0;i<n;i++)
	for(int j=0;j<n;j++)B.a[i][j]=read();
	for(int i=0;i<n;i++)I.a[i][i]=1;
	node ans=(node(I,B,O)^(r/q))*solve(p,q,r,l,node(A,I,A),node(I,B,O));
	for(int i=0;i<n;i++,puts(""))
	for(int j=0;j<n;j++)
	cout<<ans.s.a[i][j]<<" ";
	return 0;
}

用这个方法就可以很简单的水掉前面那么一大截复杂的计算的式子
但是懒得做了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值