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; 
    } 
    
  • 相关阅读:
    oracle里的tns是什么意思
    什么是联机分析处理(OLAP)
    JDBC和ODBC
    mysql 乱码
    eclipse常用快捷键和插件
    数仓项目01:准备工作
    github、maven、idea初始化一个项目
    数仓项目02:集群搭建
    数仓项目03:数据采集层(Flume+Kafka)
    Java Swing 日期控件(转载)
  • 原文地址:https://www.cnblogs.com/heyujun/p/10226274.html
Copyright © 2011-2022 走看看