看着好像很不可做的样子,那我们首先考虑一下这道题的弱化版:
假设所有的边权等于或,那么我们可以这么考虑这个矩阵:
表示从到的路径长度为的条数是多少,那么我们考虑这样转移:
,我们发现这可以矩乘,于是我们就可以在的复杂度内解决这个问题。
那么我们考虑边权不为或的情况,我们考虑拆点:将每一个点拆成个点,我们考虑表示到点的距离为的点,因此我们发现是实际存在的点,而对于,我们向连一条边权为的边,对于原矩阵中的边,我们从向连一条边权为的边,这样我们就将原图转化成了一个边权为或的图,我们对于这个图进行矩阵乘法即可,复杂度为。
代码实现:
//Optimize
#pragma GCC optimize("Ofast")
//Head File
#include<bits/stdc++.h>
using namespace std;
#define il inline
//Variable
#define ll long long
#define ull unsigned long long
#define db double
#define lb long double
//Debug
#define B cerr<<"Break Point"<<endl;
#define P(x) cerr<<#x<<' '<<"="<<' '<<(x)<<endl;
#define p(x) cerr<<#x<<' '<<"="<<' '<<(x)<<' ';
#define ml(x) cerr<<"Size of array is "<<x*4/1024/1024<<" MB"<<endl;
//Vector
#define vc vector
#define pub push_back
#define pob pop_back
#define vbe(x) x.begin(),x.end()
//Memset
#define ms(x) memset(x,0,sizeof(x))
#define MS(x) memset(x,0x3f3f3f3f,sizeof(x))
//Pair
#define fi first
#define se second
//File
#define fin(x) freopen(x,"r",stdin)
#define fou(x) freopen(x,"w",stdout)
void fio()
{
#ifndef ONLINE_JUDGE
freopen("sample.in","r",stdin);
freopen("sample.out","w",stdout);
#endif
}
void pti()
{
double timeuse = clock()*1000.0/CLOCKS_PER_SEC;
cerr<<"Timeuse "<<timeuse<<"ms"<<endl;
}
void end()
{
pti();
exit(0);
}
//Inf
#define INF 0x3f3f3f3f
#define LINF ((long long)(0x3f3f3f3f3f3f3f3f))
//IO
namespace io
{
const int SIZ=55;int que[SIZ],op,qr;char ch;
template<class I>
il void gi(I &w)
{
ch=getchar(),op=1,w=0;while(!isdigit(ch)){if(ch=='-') op=-1;ch=getchar();}
while(isdigit(ch)){w=w*10+ch-'0';ch=getchar();}w*=op;
}
template<class I>
il void print(I w)
{
qr=0;if(!w) putchar('0');if(w<0) putchar('-'),w=-w;while(w) que[++qr]=w%10+'0',w/=10;
while(qr) putchar(que[qr--]);
}
}
using io::gi;
using io::print;
const int M=105;
const ll mod=2009;
int n,m;
ll t;
struct matrix
{
ll a[M][M];
matrix(){memset(a,0,sizeof(a));}
matrix operator*(const matrix &x)const
{
matrix res;
for(int k=1;k<=m;++k)
for(int i=1;i<=m;++i)
for(int j=1;j<=m;++j)
res.a[i][j]=(res.a[i][j]+a[i][k]*x.a[k][j]%mod)%mod;
return res;
}
};
int getid(int x,int y)
{
return x+y*n;
}
int main()
{
fio();
gi(n),gi(t);
m=n*9;
matrix g;
for(int i=1;i<=n;++i)
{
for(int j=1;j<=8;++j) g.a[getid(i,j)][getid(i,j-1)]=1;
for(int j=1,x;j<=n;++j)
{
scanf("%1d",&x);
if(x) g.a[i][getid(j,x-1)]=1;
}
}
matrix sum;
for(int i=1;i<=n;++i) sum.a[i][i]=1;
while(t)
{
if(t&1) sum=sum*g;
g=g*g;
t>>=1;
}
print(sum.a[1][n]);
end();
}
来源:CSDN
作者:_DAG_
链接:https://blog.csdn.net/CaptainDAG/article/details/103704174