zoukankan      html  css  js  c++  java
  • 【BZOJ1875】【矩阵乘法】[SDOI2009]HH去散步

    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。

    Output

    一行,表示答案。

    Sample Input

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

    Sample Output

    4

    HINT

    对于30%的数据,N ≤ 4,M ≤ 10,t ≤ 10。
    对于100%的数据,N ≤ 20,M ≤ 60,t ≤ 230,0 ≤ A,B<n,0 ≤="" ai,bi="" <n。<="" p="">

    【分析】

    这个,能算数学吧...(其实是DP)

    简单的矩阵乘法,练下手。

      1 /*
      2 宋代朱敦儒
      3 《西江月·世事短如春梦》
      4 世事短如春梦,人情薄似秋云。不须计较苦劳心。万事原来有命。
      5 幸遇三杯酒好,况逢一朵花新。片时欢笑且相亲。明日阴晴未定。 
      6 */
      7 #include <cstdio>
      8 #include <cstring>
      9 #include <algorithm>
     10 #include <cmath>
     11 #include <queue>
     12 #include <vector>
     13 #include <iostream>
     14 #include <string>
     15 #include <ctime>
     16 #define LOCAL
     17 const int MAXN = 60 * 2 + 10;
     18 const int MOD = 45989;
     19 const double Pi = acos(-1.0);
     20 long long G = 15;//原根 
     21 const int MAXM = 60 * 2 + 10; 
     22 using namespace std;
     23 //读入优化 
     24 void read(int &x){
     25     char ch;x = 0;
     26     int flag = 1;
     27     ch = getchar();
     28     while (ch < '0' || ch > '9') {if (ch == '0') flag = -1; ch = getchar();}
     29     while (ch >= '0' && ch <= '9') {x = x * 10 + (ch - '0'); ch = getchar();}
     30     x *= flag;
     31 }
     32 
     33 struct Edge{
     34        int u, v;
     35 }edge[MAXM];
     36 int M;
     37 struct Matrix{
     38        int num[MAXN][MAXN];
     39        //Matrix(){memset(num, 0, sizeof(num));}
     40        Matrix operator * (const Matrix &b){
     41               Matrix c;
     42               memset(c.num, 0, sizeof(c.num));
     43               for (int i = 1; i < M; i++)
     44               for (int j = 1; j < M; j++)
     45               for (int k = 1; k < M; k++){
     46                   //if (i == 5 && j == 9)
     47                   //printf("");
     48                   c.num[i][j] = (c.num[i][j] + num[i][k] * b.num[k][j]) % MOD;
     49               }
     50               return c;
     51        }
     52 }x1, x2, x3;
     53 Matrix pow(Matrix a, int b){
     54        if (b == 1) return a;
     55        Matrix tmp = pow(a, b / 2);
     56        if (b % 2 == 0) return tmp * tmp;
     57        else return (tmp * tmp) * a; 
     58 }
     59 int n, m, t, A, B, head[MAXN], next[MAXM];
     60 
     61 //无向边 
     62 void addEdge(int u, int v){
     63      edge[M].u = u; edge[M].v = v;
     64      next[M] = head[u];
     65      head[u] = M++;
     66      
     67      edge[M].u = v; edge[M].v = u;
     68      next[M] = head[v];
     69      head[v] = M++;
     70 }
     71 void init(){
     72      memset(x1.num, 0, sizeof(x1.num));
     73      memset(x2.num, 0, sizeof(x2.num));
     74      memset(x3.num, 0, sizeof(x3.num));
     75      memset(head, -1, sizeof(head));
     76      read(n);read(m);
     77      read(t);read(A);read(B);
     78      M = 2;//注意这里要人为规定一个源 
     79      for (int i = 1; i <= m; i++){
     80          int u, v;
     81          read(u);read(v);
     82          addEdge(u, v);
     83      }
     84 } 
     85 void prepare(){
     86      for (int i = head[A]; i != -1; i = next[i]) x1.num[1][i]++;
     87      
     88      for (int i = 2; i < M; i++)
     89      for (int j = 2; j < M; j++)
     90      if (edge[i].v == edge[j].u && (i ^ 1) != j) x2.num[i][j]++;//注意这里是以边来相连 
     91 /*
     92      for (int i = 1; i < M; i++){
     93          for (int j = 1; j < M ; j++) printf("%d ", x2.num[i][j]);
     94          printf("
    ");
     95      }*/
     96 }
     97 void work(){
     98      int Ans = 0;
     99      x1 = x1 * pow(x2, t - 1); 
    100      /*for (int i = 1; i < M; i++){
    101          for (int j = 1; j < M ; j++) printf("%d ", x1.num[i][j]);
    102          printf("
    ");
    103      }*/
    104      for (int i = head[B]; i != -1; i = next[i]) Ans = (Ans + x1.num[1][i ^ 1]) % MOD;
    105      printf("%d
    ", Ans); 
    106 }
    107 
    108 int main(){
    109     init();
    110     prepare();
    111     work();
    112     return 0;
    113 }
    View Code
  • 相关阅读:
    【译】用 Rust 实现 csv 解析-part3
    【译】用 Rust 实现 csv 解析-part2
    【译】用 Rust 实现 csv 解析-part1
    【译】Rust 中的 char 和 Go 中的 rune 有什么区别?
    【译】TCP/IP 网络编程基础系列-数值编码
    【译】我最喜欢的 Rust 函数签名
    Rust 学习之运算符重载
    java.util.ConcurrentModificationException: null 问题分析解决
    2020年
    科目三夜间灯光模拟
  • 原文地址:https://www.cnblogs.com/hoskey/p/4381512.html
Copyright © 2011-2022 走看看