[FJOI2018]城市路径问题
#include
#define ll long long
using namespace std;
const ll P=1e9+7,N=1e3+2;
ll n,q,k,u,v,d;
struct node{
ll n,m;
vector> a;
void res(ll x,ll y,ll k){
n=x,m=y;
a.resize(n+1,vector(m+1));
clear(k);
}
void clear(ll x){
for(ll i=1;i<=n;i++){
for(ll j=1;j<=m;j++) a[i][j]=0;
}
if(n!=m) return ;
for(ll i=0;i<=n;i++) a[i][i]=x;
}
}O,I;
node operator*(node a,node b){
node ans;
ans.res(a.n,b.m,0);
if(a.m!=b.n) return ans;
for(ll i=0;i<=a.n;i++){
for(ll j=0;j<=b.m;j++){
for(ll k=0;k<=a.m;k++){
//if(!a.a[i][k]) continue;
ans.a[i][j]=(ans.a[i][j]+a.a[i][k]*b.a[k][j]%P)%P;
}
}
}
return ans;
}
node qpow(node a,ll b){
node ans;
ans.res(a.n,a.m,1);
while(b){
if(b&1) ans=ans*a;
a=a*a;
b>>=1;
}
return ans;
}
int main(){
scanf("%lld%lld",&n,&k);
O.res(n,k,0);
I.res(k,n,0);
for(ll i=1;i<=n;i++){
for(ll j=1;j<=k;j++) scanf("%lld",&O.a[i][j]);
for(ll j=1;j<=k;j++) scanf("%lld",&I.a[j][i]);
}
I.a[0][0]=O.a[0][0]=1;
scanf("%lld",&q);
while(q--){
scanf("%lld%lld%lld",&u,&v,&d);
O.a[v][0]=1;
node C=O*qpow(I*O,d);//为什么要多乘上一个O???
printf("%lld\n",C.a[u][0]);//答案为什么是这个??
O.a[v][0]=0;
}
return 0;
}
谢谢!
很明显的矩阵快速幂,发现如果是整个矩阵拿去搞的话 1000^3
就爆炸了,考虑可以把转移拆开,只有第一次和最后一次是 1000 × 20 的转移,中间的都是 20 × 20 的转移,直接做就好了。