[SCOI2009]迷路

我是研究僧i 提交于 2019-12-26 00:37:32

题目链接

看着好像很不可做的样子,那我们首先考虑一下这道题的弱化版:

假设所有的边权等于1100,那么我们可以这么考虑这个矩阵:

f[k][i][j]f[k][i][j]表示从iijj的路径长度为kk的条数是多少,那么我们考虑这样转移:

f[k][i][j]=f[k1][i][t]+f[1][t][j]f[k][i][j]=f[k-1][i][t]+f[1][t][j],我们发现这可以矩乘,于是我们就可以在O(n3logT)O(n^3logT)的复杂度内解决这个问题。

那么我们考虑边权不为0011的情况,我们考虑拆点:将每一个点拆成99个点,我们考虑z[i][j]z[i][j]表示到点ii的距离为jj的点,因此我们发现z[i][0]z[i][0]是实际存在的点,而对于z[i][j]z[i][j],我们向z[i][j1]z[i][j-1]连一条边权为11的边,对于原矩阵中的边,我们从z[u][0]z[u][0]z[v][val1]z[v][val-1]连一条边权为11的边,这样我们就将原图转化成了一个边权为0011的图,我们对于这个图进行矩阵乘法即可,复杂度为O((9n)3logT)O((9n)^3logT)

代码实现:

//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();
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!