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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章