P3758可樂

https://www.luogu.com.cn/problem/P3758
兩種思路:
①考慮鄰接矩陣的冪對於圖的意義。矩陣乘法定義如下ai,j=ai,kak,ja_{i,j}=a_{i,k}*a_{k,j}
所以矩陣的2次冪 就相當於此矩陣在2秒後的移動狀態。
②分層圖dp(這個我還不咋會),然後那個轉移方程可以用矩陣乘法來加速運算,從而達到優化。那個矩陣推出來是鄰接矩陣。(我還不會推。推出來想必很好的。可以更好的理解這個題)

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int siz=40;
const ll mod=2017;
// 矩陣快速冪啊,和快速冪一個思路。二進制真是一個好東西。
//以前我覺得我很會二進制,結果前幾天揹包的二進制優化都忘記了。很多東西都是自以爲是,自誤以久,應該改正。
struct Mat{
      ll mat[siz+1][siz+1];
};
Mat operator *(Mat a,Mat b){
    Mat rel;
    //memset(rel.mat,0,sizeof(rel.mat));
    for(int i=1;i<=siz;i++){
        for(int j=1;j<=siz;j++){
                rel.mat[i][j]=0;
            for(int k=1;k<=siz;k++){
                rel.mat[i][j]=((a.mat[i][k]*b.mat[k][j])%mod+rel.mat[i][j])%mod;
            }
        }
    }
    return rel;
}
Mat operator^(Mat a,int n){
     Mat rel;
     memset(rel.mat,0,sizeof(rel.mat));
     for(int i=1;i<=siz;i++)rel.mat[i][i]=1;
     while(n){
          int jud=n&1;
          if(jud)rel=rel*a;
          a=a*a;
          n>>=1;
     }
     return rel;
}
void show_detai(Mat x,int m){
     for(int i=1;i<=m;i++){
        for(int j=1;j<=m;j++)
            cout<<x.mat[i][j]<<" ";
        cout<<endl;
     }
}
void work_fbnq(){
     Mat x;
    x.mat[1][1]=1;
    x.mat[1][2]=2;
    x.mat[2][1]=1;
    x.mat[2][2]=2;
    Mat rel;
    rel=x^2;
    /*for(int i=1;i<=2;i++){
        for(int j=1;j<=2;j++)
            cout<<rel.mat[i][j]<<" ";
        cout<<endl;
    }*/
}
int main()
{   int m,n,t,a,b;
    Mat rel;
    memset(rel.mat,0,sizeof(rel.mat));
    cin>>m>>n;
    for(int i=1;i<=n;i++){
        cin>>a>>b;
        rel.mat[a][b]=1;
        rel.mat[b][a]=1;
    }
    for(int i=1;i<=m+1;i++)rel.mat[i][i]=1,rel.mat[i][m+1]=1;
    cin>>t;
    Mat re=rel^(t);
    int sum=0;
    for(int i=1;i<=(m+1);i++)
        sum=(sum+re.mat[1][i])%mod;
    cout<<sum<<endl;






    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章