zoukankan      html  css  js  c++  java
  • 【BZOJ2004】[HNOI2010]Bus 公交线路

    【BZOJ2004】[HNOI2010]Bus 公交线路

    题面

    bzoj

    洛谷

    题解

    $N$特别大$P,K$特别小,一看就是矩阵快速幂+状压

    设$f[S]$表示公交车状态为$S$的方案数

    这是什么意思呢?

    其实就是表示一个位置是否是公交车最后停靠的位置的状态

    剔除无效状态后大约只有$125$左右的状态

    直接存矩阵里快速幂转移就好了

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    #define Mod 30031
    #define RG register
    int SIZE; 
    struct Matrix {
        int a[135][135];
    	Matrix() { clear(); }
        inline void clear() { memset(a, 0, sizeof(a)); }
        void init() { clear(); for (int i = 0; i < SIZE; i++) a[i][i] = 1; }
    	inline void add(int &x, int y) { x += y; if (x >= Mod) x -= Mod; }
        inline int *operator [] (int id) { return a[id]; } 
        inline Matrix operator * (const Matrix &b) { 
            Matrix c;
            for (RG int i = 0; i < SIZE; i++)
                for (RG int j = 0; j < SIZE; j++)
                    for (RG int k = 0; k < SIZE; k++)
    					add(c[i][k], a[i][j] * b.a[j][k] % Mod); 
            return c; 
        } 
    } S; 
    int N, P, K;
    int w[1 << 12], v[1 << 12]; 
    Matrix fpow (Matrix x, int y) {
        Matrix res; res.init();
        while (y) {
            if (y & 1) res = res * x;
            x = x * x;
            y >>= 1; 
        }
        return res; 
    } 
    int main () { 
        scanf("%d%d%d", &N, &K, &P);
        for (int i = 1; i < (1 << P); i++) {
            int res = 0, x = i; 
            while (x) ++res, x -= x & (-x);
            if (res == K && (i & (1 << P - 1))) w[i] = ++SIZE, v[SIZE] = i; 
        } 
        for (int i = 1; i <= SIZE; i++) {
            if (v[i] & 1) S[i - 1][w[(1 << P - 1) | (v[i] >> 1)] - 1] = 1; 
            else {
                for (int j = 0; j < P; j++)
                     if (v[i] & (1 << j))
                         S[i - 1][w[(1 << P - 1) | ((v[i] ^ (1 << j)) >> 1)] - 1] = 1;
            } 
        } 
        S = fpow(S, N - K); 
        int i = w[(1 << P) - (1 << (P - K))]; 
        printf("%d
    ", S[i - 1][i - 1]); 
        return 0; 
    } 
    
  • 相关阅读:
    微信小程序获取用户绑定手机号码完整版
    SQL读取当天的数据
    Android 百度离线地图(由apk文件转入手机内部存储)
    解决windows家庭版系统不支持远程桌面功能问题
    微信小程序携参跳转页面
    微信小程序 websocket 封装
    微信小程序HTTP请求封装
    Ionic项目打包Android在9版本以上不能进行HTTP通信问题
    Ionic 使用 MQTT
    Ionic HTTP 请求
  • 原文地址:https://www.cnblogs.com/heyujun/p/10226274.html
Copyright © 2011-2022 走看看