zoukankan      html  css  js  c++  java
  • 洛谷 P2151 [SDOI2009]HH去散步

    题目链接

    思路

    如果没有不能走上一条边的限制,很显然就是dp。

    设f[i][j]表示到达i点走了j步的方案数,移到k点可以表示为f[k][j+1]+=f[i][j]。

    如果有限制的话,可以考虑用边表示将之前思路中的i变为边的终点,只要不走同一条边,转移还是相同的。

    但是t ≤ 2^30,显然直接dp是不可行的,这是机智的题解就想到了矩阵优化。

    由于递推关系是线性的,可以搞一个行矩阵表示对于当前移动步数各个边的方案数。

    转移可以考虑构造另一个矩阵,所有可以更新的边之间都变为1,其他是0,对于每一次转移都是一样的,所以只要将矩阵跑t次就可以了。

    对于初始矩阵,可以加一条边设一个不存在的点,将它与起点相连,也方便之后的领接表。

    此题疯狂卡时,辣鸡出题人。(据说多交几次就可以过

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 using namespace std;
     5 const int mod=45989;
     6 int n,m,t,e,s,cnt,hd[125],sum;
     7 struct edge
     8 {
     9     int to,from,nxt;
    10 }v[125];
    11 struct mat
    12 {
    13     int a[125][125];
    14     mat()
    15     {
    16         memset(a,0,sizeof(a));
    17     }
    18     mat operator * (mat x)
    19     {
    20         mat ans;
    21         for(int i=1;i<=cnt;i++)
    22             for(int j=1;j<=cnt;j++)
    23                 for(int k=1;k<=cnt;k++)
    24                     ans.a[i][j]=(ans.a[i][j]+a[i][k]*x.a[k][j])%mod;
    25         return ans;
    26     }
    27 }c,ans;
    28 void addedge(int x,int y)
    29 {
    30     v[++cnt].nxt=hd[x];
    31     v[cnt].from=x;
    32     v[cnt].to=y;
    33     hd[x]=cnt;
    34 }
    35 mat mul(mat x,int k)
    36 {
    37     mat res;
    38     for(int i=1;i<=cnt;i++)
    39         res.a[i][i]=1;
    40     for(int i=k;i;i>>=1,x=x*x)
    41         if(i&1)
    42             res=res*x;
    43     return res;
    44 }
    45 int main()
    46 {
    47     scanf("%d%d%d%d%d",&n,&m,&t,&s,&e);
    48     s++,e++;
    49     addedge(0,s);
    50     for(int i=1;i<=m;i++)
    51     {
    52         int x,y;
    53         scanf("%d%d",&x,&y);
    54         x++,y++;
    55         addedge(x,y),addedge(y,x);
    56     }
    57     for(int i=1;i<=cnt;i++)
    58         for(int j=1;j<=cnt;j++)
    59             if((i^j)!=1&&v[i].to==v[j].from)
    60                 c.a[i][j]=1;
    61     ans.a[1][1]=1;
    62     c=mul(c,t);
    63     ans=ans*c;
    64     for(int i=1;i<=cnt;i++)
    65         if(v[i].to==e)
    66             sum=(sum+ans.a[1][i])%mod;
    67     printf("%d
    ",sum);
    68     return 0;
    69 }
    View Code
  • 相关阅读:
    ASPxGridView之ASPxGridViewExporter
    Asp.net中,从弹出窗体取选择值
    ASPxGridView中常用操作
    asp.net Webconfig
    白皮书 CPU卡基本知识
    Linux 中的计时 转自IBM china
    网络无缝融合技术(转)
    UMA相关的网站
    几本不错的书
    手机基带芯片供应商严阵以待,备战3G市场
  • 原文地址:https://www.cnblogs.com/fantasquex/p/9377960.html
Copyright © 2011-2022 走看看