P2151 [SDOI2009]HH去散步

Posted Jozky86

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2151 [SDOI2009]HH去散步相关的知识,希望对你有一定的参考价值。

P2151 [SDOI2009]HH去散步

题意:

HH有个一成不变的习惯,喜欢饭后百步走。所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离。 但是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回。 又因为HH是个喜欢变化的人,所以他每天走过的路径都不完全一样,他想知道他究竟有多 少种散步的方法。

现在给你学校的地图(假设每条路的长度都是一样的都是1),问长度为t,从给定地 点A走到给定地点B共有多少条符合条件的路径

题解:

这题跟裸的矩阵快速幂唯一区别是,本题中不允许刚经过的边,本题中给的是无向边,顿时没有什么思路。
我们可以点边互换,将边成是点,然后再重新建边,如果原图中有4个边,分别编号1~4,然后我们依次判断第i个边的尾和第j个边的头是否连接,如果连接就从第i个边向第j个边连一条边,
如何处理走回去的情况,只要我们同一条边拆出来的两个点互不连边即可

代码:

// Problem: P2151 [SDOI2009]HH去散步
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2151
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// Data:2021-08-13 16:47:00
// By Jozky
#include <bits/stdc++.h>
#include <unordered_map>
#define debug(a, b) printf("%s = %d\\n", a, b);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
clock_t startTime, endTime;
//Fe~Jozky
const ll INF_ll= 1e18;
const int INF_int= 0x3f3f3f3f;
template <typename T> inline void read(T& x)
{
    T f= 1;
    x= 0;
    char ch= getchar();
    while (0 == isdigit(ch)) {
        if (ch == '-')
            f= -1;
        ch= getchar();
    }
    while (0 != isdigit(ch))
        x= (x << 1) + (x << 3) + ch - '0', ch= getchar();
    x*= f;
}
template <typename T> inline void write(T x)
{
    if (x < 0) {
        x= ~(x - 1);
        putchar('-');
    }
    if (x > 9)
        write(x / 10);
    putchar(x % 10 + '0');
}

const int maxn= 151, mod= 45989;
int n, m, s, t, x[maxn], y[maxn], cnt;
ll T;
struct Ma
{
    ll m[maxn][maxn];
};
Ma mul(Ma a, Ma b, int n)
{
    Ma temp;
    memset(&temp, 0, sizeof(temp));
    for (int i= 1; i <= n; i++) {
        for (int j= 1; j <= n; j++) {
            for (int k= 1; k <= n; k++) {
                temp.m[i][j]= (temp.m[i][j] + ((a.m[i][k] % mod) * (b.m[k][j]) % mod) % mod) % mod;
            }
        }
    }
    return temp;
}
Ma poww(Ma res, ll N, int n)
{
    Ma ans;
    for (int i= 1; i <= n; i++) {
        ans.m[i][i]= 1;
    }
    while (N) {
        if (N & 1)
            ans= mul(ans, res, n);
        res= mul(res, res, n);
        N>>= 1;
    }
    return ans;
}
Ma A;
void add(int u, int v)
{
    x[++cnt]= u;
    y[cnt]= v;
}
int main()
{
    //rd_test();
    scanf("%d%d%lld%d%d", &n, &m, &T, &s, &t);
    s++;
    t++;
    x[++cnt]= 0;
    y[cnt]= s;
    for (int i= 1, u, v; i <= m; i++) {
        scanf("%d%d", &u, &v);
        u++, v++;
        x[++cnt]= u, y[cnt]= v;
        x[++cnt]= v, y[cnt]= u;
    }
    for (int i= 1; i <= cnt; i++)
        for (int j= 1; j <= cnt; j++)
            if (i != j && i != (j ^ 1)) {
                if (y[i] == x[j])
                    A.m[i][j]= 1;
            }
    Ma Ans= poww(A, T, cnt);
    int ans= 0;
    for (int i= 1; i <= cnt; i++)
        if (y[i] == t) {
            ans= (ans + Ans.m[1][i]) % mod;
        }
    cout << ans << endl;
    return 0;
    //Time_test();
}

以上是关于P2151 [SDOI2009]HH去散步的主要内容,如果未能解决你的问题,请参考以下文章

洛谷P2151[SDOI2009]HH去散步

[bzoj1875] [洛谷P2151] [SDOI2009] HH去散步

P2151 [SDOI2009]HH去散步

[SDOI2009]HH去散步

bzoj1875SDOI2009HH去散步

BZOJ 1875[SDOI2009]HH去散步