BZOJ1875 [SDOI2009]HH去散步

矩阵优化DP。

然而本题用到了骚操作,就是没有办法沿原路走回去,所以我们不能按临接矩阵dp,需要按照边建图

两边联通当且仅当a.from==b.to所以转移dp[i][j]=dp[i][k]*dp[k][j]

多少次就是多少次幂,然后加上与终点联通边的就是答案了。

By:大奕哥

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=2005,mod=45989;
 4 struct edge{
 5     int from,to;
 6 }e[N<<1];
 7 int cnt=-1,n,m,A,B,t;
 8 void add(int x,int y)
 9 {
10     cnt++;e[cnt].to=y;e[cnt].from=x;
11     cnt++;e[cnt].to=x;e[cnt].from=y;
12 }
13 struct node
14 {
15     int n,m,s[125][125];
16     node (){
17         n=m=0;memset(s,0,sizeof(s));
18     }
19     node operator *(const node B)const{
20         node c;c.n=n;c.m=B.m;
21         for(int k=0;k<=m;++k)
22         for(int i=0;i<=n;++i)
23         for(int j=0;j<=B.m;++j)
24         c.s[i][j]=(c.s[i][j]+1ll*s[i][k]*B.s[k][j]%mod)%mod;
25         return c;
26     }
27     void print()
28     {
29         for(int i=0;i<=n;++i)
30         {for(int j=0;j<=m;++j)
31         cout<<s[i][j]<<" ";
32         cout<<endl;}
33     }
34 }b;
35 node qmod(node a,int x)
36 {
37     x--;node ans;ans=a;
38     while(x)
39     {
40         if(x&1)ans=ans*a;
41         a=a*a;x>>=1;
42     }
43     return ans;
44 }
45 int main()
46 {
47     scanf("%d%d%d%d%d",&n,&m,&t,&A,&B);int x,y;
48     for(int i=1;i<=m;++i)
49     {
50         scanf("%d%d",&x,&y);
51         add(x,y);
52     }
53     b.n=b.m=cnt;
54     for(int i=0;i<=cnt;++i)
55     for(int j=0;j<=cnt;++j)
56     {
57         if(j==(i^1)||e[i].to!=e[j].from)continue;
58         b.s[i][j]=1;
59     }
60     node ans;ans.n=1;ans.m=cnt;int sum=0;
61     for(int i=0;i<=cnt;++i)
62     if(e[i].from==A)ans.s[0][i]=1;
63     ans=ans*qmod(b,t-1);
64     for(int i=0;i<=cnt;++i)
65     if(e[i].to==B)sum=(sum+ans.s[0][i])%mod;
66     printf("%d\n",sum);
67     return 0;
68 }

 

posted @ 2018-01-23 16:45  大奕哥&VANE  阅读(166)  评论(0编辑  收藏  举报