模板
傳送門
由於太懶以下直接用a/b表示⌊ba⌋
如果有乘除疊一起會單獨打括號區分乘除的地方
1、f:
求f(a,b,c,n)=∑i=0n(ai+b)/c
當a=0時
f=(n+1)(b/c)
否則若有a≥c∣∣b≥c
f=i=0∑n(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)
當a<c且b<c時
令m=(an+b)/c
f=i=0∑nj=1∑m[j≤(ai+b)/c]
f=i=0∑nj=0∑m−1[j+1<(ai+b+1)/c]
=i=0∑nj=0∑m−1[i>(jc+c−b−1)/a]
=j=0∑m−1i=0∑n[i>(jc+c−b−1)/a]
=j=0∑m−1n−(jc+c−b−1)/a
=nm−f(c,c−b−1,a,m−1)
顯然複雜度爲O(logn)
2:g,h
求g(a,b,c,n)=∑i=0n((ai+b)/c)2
h(a,b,c,n)=∑i=0ni((ai+b)/c)
首先類似
a=0時
g=(n+1)(b/c)2,h=n∗(n+1)/2∗(b/c)
當a≥c∣∣b≥c時
類似之前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)∗(2n+1)/6∗(a/c)2+(n+1)∗(b/c)2
h=h(a%c,b%c,c,n)+n∗(n+1)∗(2n+1)/6∗(a/c)+n∗(n+1)/2∗(b/c)
當a<c且b<c時
設m=(an+b)/c
g=i=0∑n((ai+b)/c)2
=2∗i=0∑nj=1∑(ai+b)/cj−i=0∑n(ai+b)/c=−f(a,b,c,n)+2i=0∑nj=0∑m−1(j+1)[jc+c<ai+b+1]=−f+2j=0∑m−1(j+1)[i>(jc+c−b−1)/a]=−f+2j=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)
h=i=0∑ni((ai+b)/c)=i=0∑nij=0∑m−1[i>(jc+c−b−1)/a]=j=0∑m−1i=0∑ni[i>(jc+c−b−1)/a]=m∗n∗(n+1)/2−j=0∑m−1i=0∑ni[i≤(jc+c−b−1)/a]=m∗n∗(n+1)/2−j=0∑m−1i=0∑(jc+c−b−1)/ai=m∗n∗(n+1)/2−j=0∑m−1((jc+c−b−1)/a)∗((jc+c−b−1)/a+1)/2=21(m∗n∗(n+1)−i=0∑m−1((jc+c−b−1)/a)2−i=0∑m−1((jc+c−b−1)/a))=21(m∗n∗(n+1)−f(c,c−b−1,a,m−1)−g(c,c−b−1,a,m−1))
複雜度O(logn)
萬能歐幾里得
傳送門
求∑i=1lAiB(pi+r)/q
考慮這樣一個操作
維護一個三元組a,b,s
考慮一條線段y=(px+r)/q
在(0,L]內從左往右走
每當線段碰到x=c時令a=a∗A
每當碰到y=c時令b=b∗B
對於整點先進行y=c再進行x=c
每次操作後令new s=s+A∗B
顯然這和原來求得東西等價
觀察到這是一個線性變換,擁有結合律
萬能歐幾里得能利用壓縮信息在O(logT(n))的時間求出這個東西
考慮當r≥q時令r=r%q不會對操作序列產生影響
只是初始的b會變成br/q,先做即可
設函數爲f(p,q,r,l,a,b)
當p≥q時
設k=(p/q)
那麼考慮線段爲y=kx+((p%q)x+r)/q
那麼每次x加一前必定會至少有k次y的變化
於是可以直接遞歸f(p%q,q,r,l,bk∗a,b)
否則考慮可以翻轉座標軸,將x,y反過來
翻轉後的函數就是反函數
爲x=(qy−r)/p
但是這時候如果按照原來的在整點時候的計算順序就反了
於是考慮變成x=(qy−r−1)/p強制先計算x
設k=(pl+r)/q
考慮翻轉後求y∈(1,k]範圍內的
那顯然要先把前面沒計算的部分求了
就是a(q−r−1)/p∗b
考慮把y∈(1,k]→y∈(0,k−1]
那麼函數就變成x=(qy+q−r−1)/p
於是遞歸f(q,p,q−r−l,k−1,b,a)
但是k之後可能還有一些x沒被計算到
個數是l−(kq−r−1)/p
於是在後面乘上一個al−(kq−r−1)/p即可
複雜度應該是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;
}
用這個方法就可以很簡單的水掉前面那麼一大截複雜的計算的式子
但是懶得做了