Codeforces 576D Flights for Regular Customers 矩阵快速幂 (看题解)

Flights for Regular Customers

临接矩阵的 k 次 就是 恰好 走 k 步从 i 走到 j 的方案数, 方案数在这里并不关键, 所以可以把它变成01矩阵。

一个很直观的想法是用二分取check它, 但是这并不单调。。 然后就不会了。。

我们可以把G[ n - 1] [ n - 1 ] 变成  1 , 这个函数就变成单调了, 然后直接二分check就好了, 可以用bitset优化一下, 不优化其实也能过。

还有一种方法就是, 每新加入一条边, 我们暴力跑一遍图取check就好啦。

#include<bits/stdc++.h>
#define LL long long
#define LD long double
#define ull unsigned long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ALL(x) (x).begin(), (x).end()
#define fio ios::sync_with_stdio(false); cin.tie(0);

using namespace std;

const int N = 150 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-8;
const double PI = acos(-1);

template<class T, class S> inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;}
template<class T, class S> inline void sub(T& a, S b) {a -= b; if(a < 0) a += mod;}
template<class T, class S> inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;}
template<class T, class S> inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;}

const int MN = 150;

struct Matrix {
    bitset<MN> a[MN];
    void init() {
        for(int i = 0; i < MN; i++)
            a[i][i] = 1;
    }
    void setVal(int c[MN][MN]) {
        for(int i = 0; i < MN; i++)
            for(int j = 0; j < MN; j++)
                a[i][j] = c[i][j];
    }
    Matrix operator * (const Matrix& B) const {
        Matrix C;
        for(int i = 0; i < MN; i++)
            for(int j = 0; j < MN; j++)
                if(a[i][j]) C.a[i] |= B.a[j];
        return C;
    }
    Matrix operator ^ (LL b) {
        Matrix C; C.init();
        Matrix A = *this;
        while(b) {
            if(b & 1) C = C * A;
            A = A * A; b >>= 1;
        }
        return C;
    }
} mat[N], now[N], tmp;

int n, m, a[N], b[N], d[N];
int G[MN][MN];
vector<int> oo;
vector<PII> edge[N];

int main() {
    scanf("%d%d", &n, &m);
    for(int i = 0; i < m; i++) {
        scanf("%d%d%d", &a[i], &b[i], &d[i]);
        a[i]--; b[i]--;
        oo.push_back(d[i]);
    }
    oo.push_back(0);
    sort(ALL(oo));
    oo.erase(unique(ALL(oo)), oo.end());
    for(int i = 0; i < m; i++) {
        edge[lower_bound(ALL(oo), d[i]) - oo.begin()].push_back(mk(a[i], b[i]));
    }
    tmp.init();
    int p = SZ(oo) - 1;
    G[n - 1][n - 1] = 1;
    for(int i = 0; i < SZ(oo); i++) {
        now[i] = tmp;
        if(now[i].a[0][n - 1]) {
            p = i - 1;
            break;
        }
        for(auto& e : edge[i]) {
            G[e.fi][e.se] = 1;
        }
        mat[i].setVal(G);
        if(i == SZ(oo) - 1) break;
        tmp = tmp * (mat[i] ^ (oo[i + 1] - oo[i]));
    }
    Matrix gg;
    int low = 1, high = p == SZ(oo) - 1 ? 1000000200 : oo[p + 1] - oo[p], mid, step = -1;
    while(low <= high) {
        mid = low + high >> 1;
        gg = now[p] * (mat[p] ^ mid);
        if(gg.a[0][n - 1]) high = mid - 1, step = mid;
        else low = mid + 1;
    }
    if(~step) printf("%d\n", oo[p] + step);
    else puts("Impossible");
    return 0;
}

/*
*/

原文地址:https://www.cnblogs.com/CJLHY/p/10818940.html

时间: 2024-10-25 12:13:24

Codeforces 576D Flights for Regular Customers 矩阵快速幂 (看题解)的相关文章

Codeforces 576D Flights for Regular Customers 矩阵快速幂+DP

题意: 给一个\(n\)点\(m\)边的连通图 每个边有一个权值\(d\) 当且仅当当前走过的步数\(\ge d\)时 才可以走这条边 问从节点\(1\)到节点\(n\)的最短路 好神的一道题 直接写做法喽 首先我们对边按\(d_i\)由小到大排序 设\(f_i\)表示加上\(1\sim i-1\)的所有边走\(d_i\)次后各点间的联通情况 \(G\)表示只连\(1\sim i-1\)的边的邻接矩阵 这些我们可以用一个\(01\)邻接矩阵来存储 则有 \(f_i=f_{i-1}*G^{d_i-

(中等) CF 576D Flights for Regular Customers (#319 Div1 D题),矩阵快速幂。

In the country there are exactly n cities numbered with positive integers from 1 to n. In each city there is an airport is located. Also, there is the only one airline, which makes m flights. Unfortunately, to use them, you need to be a regular custo

Codeforces Round #257 (Div. 2)B 矩阵快速幂

B. Jzzhu and Sequences time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Jzzhu has invented a kind of sequences, they meet the following property: You are given x and y, please calculate fn m

Product Oriented Recurrence(Codeforces Round #566 (Div. 2)E+矩阵快速幂+欧拉降幂)

传送门 题目 \[ \begin{aligned} &f_n=c^{2*n-6}f_{n-1}f_{n-2}f_{n-3}&\\end{aligned} \] 思路 我们通过迭代发现\(f_n\)其实就是由\(c^{x_1},f_1^{x_2},f_2^{x_3},f_3^{x_4}\)相乘得到,因此我们可以分别用矩阵快速幂求出\(x_1,x_2,x_3,x_4\),最后用快速幂求得答案. 对\(f_1,f_2,f_3\): \[ \begin{aligned} (x_n&&

Codeforces 696D Legen...(AC自动机 + 矩阵快速幂)

题目大概说给几个字符串,每个字符串都有一个开心值,一个串如果包含一次这些字符串就加上对应的开心值,问长度n的串开心值最多可以是多少. POJ2778..复习下..太弱了都快不会做了.. 这个矩阵的乘法定义是不同的,m[i][j]=max(m1[i][k]+m2[k][j]),即从i走到k能获得的最大值与从k走到j能获得的最大值之和去更新从i到j能获得的最大值. 另外..关于矩阵内的初始值..用-1表示从i不能到j,比如初始的时候,i不能走一步到j结点这时值就应该设置成-1:而不能用0,因为0是有

Codeforces 551D GukiZ and Binary Operations(矩阵快速幂)

Problem E. GukiZ and GukiZiana Solution 一位一位考虑,就是求一个二进制序列有连续的1的种类数和没有连续的1的种类数. 没有连续的1的二进制序列的数目满足f[i]=f[i-1]+f[i-2],恰好是斐波那契数列. 数据范围在10^18,用矩阵加速计算,有连续的1的数目就用2^n-f[n+1] 最后枚举k的每一位,是1乘上2^n-f[n+1],是0乘上f[n+1] 注意以上需要满足 2^l>k.并且这里l的最大值为64,需要特判. #include <bit

codeforces gym #101161G - Binary Strings(矩阵快速幂)

题目链接: http://codeforces.com/gym/101161/attachments 题意: 数据范围: 分析: ac代码: #include<bits/stdc++.h> using namespace std; #define ll long long #define pii pair<int,int> const int maxn = 1e5+100; const int mod=1e9+7; struct Node{ ll num[4][4]; Node()

POJ——3070Fibonacci(矩阵快速幂)

Fibonacci Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 12329   Accepted: 8748 Description In the Fibonacci integer sequence, F0 = 0, F1 = 1, and Fn = Fn − 1 + Fn − 2 for n ≥ 2. For example, the first ten terms of the Fibonacci sequenc

【矩阵快速幂 】Codeforces 450B - Jzzhu and Sequences (公式转化)

[题目链接]click here~~ [题目大意] Jzzhu has invented a kind of sequences, they meet the following property: You are given x and y, please calculate fn modulo1000000007(109?+?7). [解题思路] /*A - Jzzhu and Sequences Codeforces 450B - Jzzhu and Sequences ( 矩阵快速幂 )