Codevs 1482 路線統計(矩陣乘法)

1482 路線統計
時間限制: 1 s
空間限制: 256000 KB
題目等級 : 鑽石 Diamond
題目描述 Description
N個節點的有向圖, 求從start到finish剛好經過時間time的總方案數 mod 502630.
輸入描述 Input Description
第一行包含一個整數n, 所有點是從0到N-1編號.
接下來n行,每行包含n個字符. 第i行第j個字符表示i到j需要的時間. 字符只可能是’1’到’5’, 或者是’.’表示i不能到達j. 保證主對角線都是’.’.
接下來一行3個整數start, finish, time.
輸出描述 Output Description
輸出總方案數.
樣例輸入 Sample Input
3
.12
2.1
12.
0 2 5
樣例輸出 Sample Output
8
數據範圍及提示 Data Size & Hint
對於20%的數據, 輸入的字符不是’1’就是’.’;
對於100%的數據, 1 <= n <= 10; 1 <= start,finish <= n; 1 <= time <= 10^9.
分類標籤 Tags
矩陣乘法 數論

/*
矩陣乘法.
沒想出來 唉. 
比較神奇.
t爲1的話直接矩陣乘法.
but 這題1<=t<=5啊.
這樣的話我們考慮拆點.
拆成這樣i1->i2->i3->i4->i5.
然後對於it(第t個點)連一條邊到j.
這樣我們每條邊的長度就都是1啦.
然後就可以轉移啦.
*/
#include<iostream>
#include<cstdio>
#define MAXN 101
#define LL long long
#define mod 502630
using namespace std;
int n,m,s,t,k;
LL ans[MAXN][MAXN],b[MAXN][MAXN],c[MAXN][MAXN];
void mi()
{
    while(k)
    {
        if(k&1)
        {
            for(int i=1;i<=n;i++)
              for(int j=1;j<=n;j++)
                for(int k=1;k<=n;k++)
                  c[i][j]=(c[i][j]+ans[i][k]*b[k][j])%mod;
            for(int i=1;i<=n;i++)
              for(int j=1;j<=n;j++)
                ans[i][j]=c[i][j],c[i][j]=0;
        }
        for(int i=1;i<=n;i++)
          for(int j=1;j<=n;j++)
            for(int k=1;k<=n;k++)
              c[i][j]=(c[i][j]+b[i][k]*b[k][j])%mod;
        for(int i=1;i<=n;i++)
          for(int j=1;j<=n;j++)
            b[i][j]=c[i][j],c[i][j]=0;
        k>>=1;
    }
}
int main()
{
    char ch;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
      for(int j=1;j<5;j++)
        ans[i+(j-1)*n][i+j*n]=b[i+(j-1)*n][i+j*n]=1;
    for(int i=1;i<=n;i++)
      for(int j=1;j<=n;j++)
      {
        cin>>ch;
        int x=int(ch-48);
        if(ch!='.') ans[i+(x-1)*n][j]=b[i+(x-1)*n][j]=1;
      }
    scanf("%d%d%d",&s,&t,&k);
    s++,t++;k--;
    n*=6;
    mi();
    cout<<ans[s][t];
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章