HDU 2157 How many ways?? 【矩陣快速冪水題,離散數學結論】

HDU 2157 How many ways??

離散數學中證明過這樣一個結論:
在這裏插入圖片描述

書上寫了一大堆,說人話 就是:
從u點到v點恰好經過k步的方案數,爲鄰接矩陣的k次冪得到的矩陣(假設是ans)中的元素ans[u][v]。

出題人比較友好,冪次比較小(k<20),不用矩陣快速冪也能過,但還是寫一下矩陣快速冪的代碼:

#include <bits/stdc++.h>
using namespace std;
const int N=22,mod=1000;
int n,m,x,y,k,q;
struct node
{
    int m[N][N];
}s;
node mul(node s1,node s2) // 兩矩陣相乘
{
    node ans;
    memset(ans.m,0,sizeof(ans.m));
    // 全部初始化爲0(結構體內不會自動初始化)
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            for(int k=0;k<n;k++)
                ans.m[i][j]=(ans.m[i][j]+s1.m[i][k]*s2.m[k][j]%mod)%mod;
    return ans;
}
node qpow(node a,int b) //  矩陣a的b次冪
{
    node ans;
    memset(ans.m,0,sizeof(ans.m));
    for(int i=0;i<n;i++)
        ans.m[i][i]=1; // ans初始化爲單位矩陣
    while(b)
    {
        if(b&1)ans=mul(ans,a);
        a=mul(a,a);
        b/=2;
    }
    return ans;
}
int main()
{
    ios::sync_with_stdio(false);
    while(cin>>n>>m&&(n||m))
    {
        memset(s.m,0,sizeof(s.m));
        for(int i=1;i<=m;i++)
        {
            cin>>x>>y;
            s.m[x][y]=1; // 如果有重邊也只算一條路
        }
        cin>>q;
        node ans;
        while(q--)
        {
            cin>>x>>y>>k;
            ans=qpow(s,k);
            printf("%d\n",ans.m[x][y]);
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章