rt,本人在『STAOI』G - Round 3 T3 中使用了未展开的矩阵乘法,喜提 TLE55pts。代码下附。
未展开的矩阵乘法常数很大么?不展开有何卡常办法?
#include<bits/stdc++.h>
using namespace std;
int M;
#define int long long
struct Mat {
int a[3][3],r,c;
Mat(int r,int c,int k):r(r),c(c){
memset(a,0,sizeof a);
for(int i=1;i<=min(c,r);i++) a[i][i]=k;
}
Mat():r(2),c(2){
memset(a,0,sizeof a);
for(int i=1;i<=min(c,r);i++) a[i][i]=1;
}
const int* operator[](const int p) const {
return a[p];
}
int* operator[](const int p) {
return a[p];
}
Mat operator*(const Mat b) const {
Mat ret(r,b.c,0);
for(int i=1;i<=r;i++) {
for(int j=1;j<=b.c;j++) {
for(int k=1;k<=c;k++) {
ret[i][j]+=a[i][k]*b[k][j]%M;
ret[i][j]%=M;
}
}
}
return ret;
}
};
Mat pow(Mat b,int p) {
Mat ret(b.r,b.c,1);
while(p>0) {
if(p&1) ret=ret*b;
b=b*b;
p>>=1;
}
return ret;
}
using Plm=pair<long long, Mat>;
map<long long,Plm> mp;
Mat raw(1,2,0);
Mat fib(2,2,0);
Mat calc(int n) {
Mat sp;
if(mp.count(M))
sp=pow(mp[M].second,n/mp[M].first)*pow(fib,n%mp[M].first);
else sp=pow(fib,n);
mp[M]=Plm{n,sp};
return raw*sp;
}
struct ask {
int M,n,id;
bool operator<(const ask b) const {
return M!=b.M?M<b.M:n<b.n;
}
}q[200010];
int ans[200010];
main() {
ios::sync_with_stdio(0);
cout.tie(0);
cin.tie(0);
raw[1][1]=0;
raw[1][2]=1;
fib[1][1]=0;
fib[1][2]=1;
fib[2][1]=1;
fib[2][2]=1;
int T;
cin>>T;
for(int i=1;i<=T;i++) {
cin>>q[i].n>>q[i].M;
q[i].id=i;
}
sort(q+1,q+1+T);
for(int i=1;i<=T;i++) {
M=q[i].M;
Mat res=calc(q[i].n);
ans[q[i].id]=(res[1][2]%M*((res[1][1]*res[1][1]%M+res[1][1])%M))%M;
}
for(int i=1;i<=T;i++) {
cout<<ans[i]<<endl;
}
}
以及,个人习惯用结构体,需不需要换成 C 风格》/kel