• BZOj-1875: [SDOI2009]HH去散步 (矩阵快速幂)


    1875: [SDOI2009]HH去散步

    Time Limit: 20 Sec  Memory Limit: 64 MB
    Submit: 1999  Solved: 980
    [Submit][Status][Discuss]

    Description

    HH有个一成不变的习惯,喜欢饭后百步走。所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离。 但
    是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回。 又因为HH是个喜欢变化的人,所以他每
    天走过的路径都不完全一样,他想知道他究竟有多 少种散步的方法。 现在给你学校的地图(假设每条路的长度都
    是一样的都是1),问长度为t,从给定地 点A走到给定地点B共有多少条符合条件的路径

    Input

    第一行:五个整数N,M,t,A,B。
    N表示学校里的路口的个数
    M表示学校里的 路的条数
    t表示HH想要散步的距离
    A表示散步的出发点
    B则表示散步的终点。
    接下来M行
    每行一组Ai,Bi,表示从路口Ai到路口Bi有一条路。
    数据保证Ai != Bi,但不保证任意两个路口之间至多只有一条路相连接。 
    路口编号从0到N -1。 
    同一行内所有数据均由一个空格隔开,行首行尾没有多余空格。没有多余空行。 
    答案模45989。
    N ≤ 20,M ≤ 60,t ≤ 2^30,0 ≤ A,B

    Output

    一行,表示答案。

    Sample Input

    4 5 3 0 0
    0 1
    0 2
    0 3
    2 1
    3 2

    Sample Output

    4

    HINT

     

    Source

    laj一开始把题目看错了= = 不能走回头路哇……laj就说这题怎么可能这么傻逼呢……
    然后就是很神的做法咯……把边存到矩阵里收尾相接的两条边在矩阵里连边,然后求t-1次幂,在开另一个矩阵,剩下的开代码qwq
    laj又忘记膜辣……wa了一发 _(:зゝ∠)_
     1 #include "bits/stdc++.h"
     2 using namespace std;
     3 typedef long long LL;
     4 const int MAX=205,mod=45989;
     5 int n,m,t,st,ed;
     6 struct Mat{
     7     int x,y;
     8     int mat[MAX][MAX];
     9     Mat(){x=y=0;memset(mat,0,sizeof(mat));}
    10     friend Mat operator * (Mat cc,Mat tt) {
    11         Mat an;int i,j,k;
    12         an.x=cc.x,an.y=tt.y;
    13         for (i=1;i<=cc.x;i++)
    14             for (k=1;k<=cc.y;k++)
    15                 if (cc.mat[i][k])
    16                     for (j=1;j<=an.y;j++)
    17                         an.mat[i][j]=(an.mat[i][j]+cc.mat[i][k]*tt.mat[k][j])%mod;
    18         return an;
    19     }
    20     friend Mat operator ^(Mat cc,int tt) {
    21         Mat an;int i,j;
    22         an.x=cc.x,an.y=cc.y;
    23         for (i=1;i<=cc.x;i++) an.mat[i][i]=1;
    24         while (tt){
    25             if (tt&1) an=an*cc;
    26             cc=cc*cc,tt>>=1;
    27         }
    28         return an;
    29     }
    30     void out(){
    31         int i,j;
    32         for (i=1;i<=x;i++){
    33             for (j=1;j<=y;j++)
    34                 printf("%d ",mat[i][j]);
    35             printf("
    ");
    36         }
    37         printf("
    ");
    38     }
    39 }a,b;
    40 struct Edge{int x,y;}edge[1005];
    41 int tot,head[MAX],adj[1005],next[1005];
    42 void addedge(int u,int v){tot++;adj[tot]=v,next[tot]=head[u],head[u]=tot,edge[tot].x=u,edge[tot].y=v;}
    43 inline int read(){
    44     int an=0,x=1;char c=getchar();
    45     while (c<'0' || c>'9') {if (c=='-') x=-1;c=getchar();}
    46     while (c>='0' && c<='9') {an=(an<<3)+(an<<1)+c-'0';c=getchar();}
    47     return an*x;
    48 }
    49 int main(){
    50     freopen ("walk.in","r",stdin);freopen ("walk.out","w",stdout);
    51     int i,j,x,y;tot=1;
    52     n=read(),m=read(),t=read(),st=read(),ed=read();st++,ed++;
    53     for (i=1;i<=m;i++){
    54         x=read(),y=read();x++,y++;
    55         addedge(x,y),addedge(y,x);
    56     }
    57     a.x=a.y=b.x=b.y=tot;
    58     for (i=head[st];i;i=next[i]) a.mat[1][i]++;
    59     for (i=2;i<=tot;i++)
    60         for (j=2;j<=tot;j++)
    61             if (edge[i].y==edge[j].x && i!=(j^1))
    62                 b.mat[i][j]++;
    63     a=a*(b^(t-1));
    64     int ans=0;
    65     for (i=head[ed];i;i=next[i])
    66         ans+=a.mat[1][i^1];
    67     printf("%d",ans%mod);
    68     return 0;
    69 }
  • 相关阅读:
    设计模式-11-代理模式
    设计模式-10-装饰者
    设计模式-9-组合
    设计模式-8-适配器
    设计模式-7-原型模式
    设计模式-6-建造者
    设计模式-5-单例模式
    u-boot-1.1.6 设置新分区支持设备树
    u-boot-2014.10移植(8)重定位,支持NAND启动
    u-boot-2014.10移植(7)修改环境变量的存储位置
  • 原文地址:https://www.cnblogs.com/keximeiruguo/p/7807046.html
Copyright © 2020-2023  润新知