2016多校联合第一场 HDU5731解题报告

题意:

给你一个n*m的矩阵,你需要用1*2或者2*1的多米诺骨牌将其全部覆盖,并且使得没有一条横线或者竖线通过矩阵

如果不看条件,此题是赤裸裸的轮廓线基础dp,赛场上利用轮廓线把行的情况处理出来,但是列就懵逼了。

思路:

首先我们用一个数组d[n][m]来存轮廓线dp求出来的值:n行m列的矩阵随意放置全部覆盖的方法数,然后状压竖向分割线,状压之后,把每一块的长度保存下来丢进v数组。然后从小到大枚举行的长度,再枚举无行分割的区域(再当前列分割下)f[i]表示从第1行到第i行,没有行分割线的方法数。f后根据列分割的状态对答案进行加成(容斥)

代码:

//  Created by Running Photon
//  Copyright (c) 2015 Running Photon. All rights reserved.
//
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define ALL(x) x.begin(), x.end()
#define INS(x) inserter(x, x,begin())
#define ll long long
#define CLR(x) memset(x, 0, sizeof x)
using namespace std;
const int inf = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 1e6 + 10;
const int maxv = 1e3 + 10;
const double eps = 1e-9;

int n, m, cur;
ll dp[2][(1 << 16) + 5];
ll d[18][18];
ll f[20];
int v[30];
void update(int past, int now) {
    if(now >> m & 1) dp[cur][now ^ (1 << m)] = (dp[cur][now ^ (1 << m)] + dp[1-cur][past]) % MOD;
}
ll calc(int row, int col) {
    ll ans = 0;
    for(int state = 0; state < (1 << col - 1); state++) {
        int num = 0; int last = -1;
        for(int i = 0; i < col - 1; i++) {
            if(state >> i & 1) {
                v[num++] = i - last;
                last = i;
            }
        }
        v[num++] = col - 1 - last;
        for(int len = 1; len <= row; len++) {
            for(int u = 0; u < len; u++) {
                ll tmp = 1;
                for(int i = 0; i < num; i++) {
                    tmp = tmp * d[len - u][v[i]] % MOD;
                }
                if(u == 0) f[len] = tmp;
                else f[len] = (f[len]  - tmp * f[u] + MOD) % MOD;
            }
        }
        if(num % 2 == 0) ans = (ans - f[row] + MOD) % MOD;
        else ans = (ans + f[row]) % MOD;
    }
    return ans;
}
int main() {
#ifdef LOCAL
    freopen("C:\\Users\\Administrator\\Desktop\\in.txt", "r", stdin);
    freopen("C:\\Users\\Administrator\\Desktop\\out.txt","w",stdout);
#endif
d[1][1] = 0;
d[1][2] = 1;
d[1][3] = 0;
d[1][4] = 1;
d[1][5] = 0;
d[1][6] = 1;
d[1][7] = 0;
d[1][8] = 1;
d[1][9] = 0;
d[1][10] = 1;
d[1][11] = 0;
d[1][12] = 1;
d[1][13] = 0;
d[1][14] = 1;
d[1][15] = 0;
d[1][16] = 1;
d[2][1] = 1;
d[2][2] = 2;
d[2][3] = 3;
d[2][4] = 5;
d[2][5] = 8;
d[2][6] = 13;
d[2][7] = 21;
d[2][8] = 34;
d[2][9] = 55;
d[2][10] = 89;
d[2][11] = 144;
d[2][12] = 233;
d[2][13] = 377;
d[2][14] = 610;
d[2][15] = 987;
d[2][16] = 1597;
d[3][1] = 0;
d[3][2] = 3;
d[3][3] = 0;
d[3][4] = 11;
d[3][5] = 0;
d[3][6] = 41;
d[3][7] = 0;
d[3][8] = 153;
d[3][9] = 0;
d[3][10] = 571;
d[3][11] = 0;
d[3][12] = 2131;
d[3][13] = 0;
d[3][14] = 7953;
d[3][15] = 0;
d[3][16] = 29681;
d[4][1] = 1;
d[4][2] = 5;
d[4][3] = 11;
d[4][4] = 36;
d[4][5] = 95;
d[4][6] = 281;
d[4][7] = 781;
d[4][8] = 2245;
d[4][9] = 6336;
d[4][10] = 18061;
d[4][11] = 51205;
d[4][12] = 145601;
d[4][13] = 413351;
d[4][14] = 1174500;
d[4][15] = 3335651;
d[4][16] = 9475901;
d[5][1] = 0;
d[5][2] = 8;
d[5][3] = 0;
d[5][4] = 95;
d[5][5] = 0;
d[5][6] = 1183;
d[5][7] = 0;
d[5][8] = 14824;
d[5][9] = 0;
d[5][10] = 185921;
d[5][11] = 0;
d[5][12] = 2332097;
d[5][13] = 0;
d[5][14] = 29253160;
d[5][15] = 0;
d[5][16] = 366944287;
d[6][1] = 1;
d[6][2] = 13;
d[6][3] = 41;
d[6][4] = 281;
d[6][5] = 1183;
d[6][6] = 6728;
d[6][7] = 31529;
d[6][8] = 167089;
d[6][9] = 817991;
d[6][10] = 4213133;
d[6][11] = 21001799;
d[6][12] = 106912793;
d[6][13] = 536948224;
d[6][14] = 720246619;
d[6][15] = 704300462;
d[6][16] = 289288426;
d[7][1] = 0;
d[7][2] = 21;
d[7][3] = 0;
d[7][4] = 781;
d[7][5] = 0;
d[7][6] = 31529;
d[7][7] = 0;
d[7][8] = 1292697;
d[7][9] = 0;
d[7][10] = 53175517;
d[7][11] = 0;
d[7][12] = 188978103;
d[7][13] = 0;
d[7][14] = 124166811;
d[7][15] = 0;
d[7][16] = 708175999;
d[8][1] = 1;
d[8][2] = 34;
d[8][3] = 153;
d[8][4] = 2245;
d[8][5] = 14824;
d[8][6] = 167089;
d[8][7] = 1292697;
d[8][8] = 12988816;
d[8][9] = 108435745;
d[8][10] = 31151234;
d[8][11] = 940739768;
d[8][12] = 741005255;
d[8][13] = 164248716;
d[8][14] = 498190405;
d[8][15] = 200052235;
d[8][16] = 282756494;
d[9][1] = 0;
d[9][2] = 55;
d[9][3] = 0;
d[9][4] = 6336;
d[9][5] = 0;
d[9][6] = 817991;
d[9][7] = 0;
d[9][8] = 108435745;
d[9][9] = 0;
d[9][10] = 479521663;
d[9][11] = 0;
d[9][12] = 528655152;
d[9][13] = 0;
d[9][14] = 764896039;
d[9][15] = 0;
d[9][16] = 416579196;
d[10][1] = 1;
d[10][2] = 89;
d[10][3] = 571;
d[10][4] = 18061;
d[10][5] = 185921;
d[10][6] = 4213133;
d[10][7] = 53175517;
d[10][8] = 31151234;
d[10][9] = 479521663;
d[10][10] = 584044562;
d[10][11] = 472546535;
d[10][12] = 732130620;
d[10][13] = 186229290;
d[10][14] = 274787842;
d[10][15] = 732073997;
d[10][16] = 320338127;
d[11][1] = 0;
d[11][2] = 144;
d[11][3] = 0;
d[11][4] = 51205;
d[11][5] = 0;
d[11][6] = 21001799;
d[11][7] = 0;
d[11][8] = 940739768;
d[11][9] = 0;
d[11][10] = 472546535;
d[11][11] = 0;
d[11][12] = 177126748;
d[11][13] = 0;
d[11][14] = 513673802;
d[11][15] = 0;
d[11][16] = 881924366;
d[12][1] = 1;
d[12][2] = 233;
d[12][3] = 2131;
d[12][4] = 145601;
d[12][5] = 2332097;
d[12][6] = 106912793;
d[12][7] = 188978103;
d[12][8] = 741005255;
d[12][9] = 528655152;
d[12][10] = 732130620;
d[12][11] = 177126748;
d[12][12] = 150536661;
d[12][13] = 389322891;
d[12][14] = 371114062;
d[12][15] = 65334618;
d[12][16] = 119004311;
d[13][1] = 0;
d[13][2] = 377;
d[13][3] = 0;
d[13][4] = 413351;
d[13][5] = 0;
d[13][6] = 536948224;
d[13][7] = 0;
d[13][8] = 164248716;
d[13][9] = 0;
d[13][10] = 186229290;
d[13][11] = 0;
d[13][12] = 389322891;
d[13][13] = 0;
d[13][14] = 351258337;
d[13][15] = 0;
d[13][16] = 144590622;
d[14][1] = 1;
d[14][2] = 610;
d[14][3] = 7953;
d[14][4] = 1174500;
d[14][5] = 29253160;
d[14][6] = 720246619;
d[14][7] = 124166811;
d[14][8] = 498190405;
d[14][9] = 764896039;
d[14][10] = 274787842;
d[14][11] = 513673802;
d[14][12] = 371114062;
d[14][13] = 351258337;
d[14][14] = 722065660;
d[14][15] = 236847118;
d[14][16] = 451896972;
d[15][1] = 0;
d[15][2] = 987;
d[15][3] = 0;
d[15][4] = 3335651;
d[15][5] = 0;
d[15][6] = 704300462;
d[15][7] = 0;
d[15][8] = 200052235;
d[15][9] = 0;
d[15][10] = 732073997;
d[15][11] = 0;
d[15][12] = 65334618;
d[15][13] = 0;
d[15][14] = 236847118;
d[15][15] = 0;
d[15][16] = 974417347;
d[16][1] = 1;
d[16][2] = 1597;
d[16][3] = 29681;
d[16][4] = 9475901;
d[16][5] = 366944287;
d[16][6] = 289288426;
d[16][7] = 708175999;
d[16][8] = 282756494;
d[16][9] = 416579196;
d[16][10] = 320338127;
d[16][11] = 881924366;
d[16][12] = 119004311;
d[16][13] = 144590622;
d[16][14] = 451896972;
d[16][15] = 974417347;
d[16][16] = 378503901;

//  ios_base::sync_with_stdio(0);
    // for(n = 1; n <= 16; n++) {
    //  for(m = 1; m <= 16; m++) {
    //      cur = 0;
    //      dp[cur][(1 << m) - 1] = 1;
    //      for(int i = 0; i < n; i++) {
    //          for(int j = 0; j < m; j++) {
    //              cur ^= 1;
    //              CLR(dp[cur]);
    //              for(int state = 0; state < 1 << m; state++) {
    //                  update(state, state << 1);
    //                  if(i && !((1 << m - 1) & state)) update(state, (state << 1) ^ (1 << m) ^ 1);
    //                  if(j && !(state & 1)) update(state, (state << 1) ^ 3);
    //              }
    //          }
    //      }
    //      d[n][m] = dp[cur][(1 << m) - 1];
    //      printf("d[%d][%d] = %lld;\n", n, m, d[n][m]);
    //  }
    // }
    while(scanf("%d%d", &n, &m) != EOF) {
        printf("%lld\n", calc(n, m));
    }
    return 0;
}

你可能感兴趣的:(动态规划,数学)