LOJ6440 万能欧几里得
Solution
Code
注意几个边界的特判。
#include<bits/stdc++.h>
using namespace std;
#define REP(i,a,b) for(int i=(a),_ed=(b);i<=_ed;++i)
#define DREP(i,a,b) for(int i=(a),_ed=(b);i>=_ed;--i)
typedef long long ll;
inline ll read(){
register ll x=0,f=1;register char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=0;ch=getchar();}
while(isdigit(ch)){x=x*10+(ch^'0');ch=getchar();}
return f?x:-x;
}
const int N=21,mod=998244353;
int _;ll p,q,r,l;
inline void inc(int &x,int y){x=x+y<mod?x+y:x+y-mod;}
inline ll div(ll n,ll a,ll b,ll c){return ((__int128)a*n+b)/c;}
struct matrix{
int x[N][N];
inline int* operator[](const int &a){return x[a];}
inline const int* operator[](const int &a)const{return x[a];}
inline matrix(int c=0){REP(i,1,_)REP(j,1,_)x[i][j]=(i==j)*c;}
inline matrix operator+(const matrix& t){
matrix res(0);
REP(i,1,_)REP(j,1,_)res[i][j]=(x[i][j]+t[i][j])%mod;
return res;
}
inline matrix operator*(const matrix &t){
matrix res(0);
REP(k,1,_)REP(i,1,_)REP(j,1,_)inc(res[i][j],1ll*x[i][k]*t[k][j]%mod);
return res;
}
inline matrix operator^(ll n){
matrix ans(1),bas=(*this);
for(;n;n>>=1,bas=bas*bas)if(n&1)ans=ans*bas;
return ans;
}
inline void print(){
REP(i,1,_)REP(j,1,_)printf("%d%c",x[i][j],j==_?'\n':' ');
}
}A,B;
struct node{
ll U,R;
matrix A,B,S;
inline node():U(0),R(0),A(1),B(1),S(0){}
inline node operator+(const node &t){
node res;
res.U=U+t.U,res.R=R+t.R;
res.A=A*t.A,res.B=B*t.B;
res.S=S+A*t.S*B;
return res;
}
inline node operator^(ll n){
node ans,bas=(*this);
for(;n;n>>=1,bas=bas+bas)if(n&1)ans=ans+bas;
return ans;
}
};
inline node solve(ll n,ll a,ll b,ll c,node A,node B){
if(!n)return node();
b%=c;
if(!a)return (A^(b/c))+(B^n);
if(a>=c)return solve(n,a%c,b,c,A,(A^(a/c))+B);
ll m=div(n,a,b,c),cnt=n-div(m,c,-b-1,a);
if(!m)return B^n;
return (B^((c-b-1)/a))+A+solve(m-1,c,c-b-1,a,B,A)+(B^(cnt));
}
int main(){
// freopen("in.in","r",stdin);
p=read(),q=read(),r=read(),l=read(),_=read();
REP(i,1,_)REP(j,1,_)A[i][j]=read();
REP(i,1,_)REP(j,1,_)B[i][j]=read();
node U,R;
U.U=1,U.B=B;
R.R=1,R.A=A,R.S=A;
node ans=(U^(r/q))+solve(l,p,r,q,U,R);
ans.S.print();
return 0;
}