HDU 5731 2016多校Contest 1 F题【轮廓线DP+容斥原理】

来源:互联网 发布:美工要学哪些 编辑:程序博客网 时间:2024/05/18 05:48

首先轮廓线DP部分:

见博客上一题。


首先一个简单的递推,f[i]表示i行元素,全部没有被横着切割的方案总数,s[i]为i行元素的总方案数。

f[i] = s[i] - sum(f[j] * s[i-j])


先求出所有竖着切的方案,比如p[i]表示连续i列,的方案总数。再求横着切的方案。

横着切的方法就是利用p数组的元素,求出在在i列(没有竖着切)的情况下,j行也没有被横着切的方案总数。

继续用上述的递推式子略微改进,进行计算的话,会出现问题


形如图所示的情况,会出现问题。

|----------------|

|     |               |

|     |       |       |

|----------|-----|


……(上传不了图了,网卡了……理解一下……)

其实就是,因为在做递推的时候,所穷举的情况,都是没有被竖着切割的情况。而需要去掉所有横着切的方案。但是这个地方出现了问题,如果要去掉这个情况,必须由2个都竖着切的方案组合而成。但是因为直接使用了p数组(前文提到)的元素进行计算,所以不存在这样的数组了。所以就不能完成计算了。


所以这样是错的…… 



首先确定一个公式,


至于这个公式怎么用我不知道……菊苣说……利用这个公式,可以得出一个结论。


先给出引出的一个题目,类似于博客里前面有过的那个计算方案总数的FFT的题:

有一条线段(长度为整数),其中长度为1的线段,有a[1]个方案来装饰(直接给长度为1的线段上色), 长度为2的线段有[2]个方法来装饰(1、直接给长度为2的线段上色有若干个方案,或者先给长度为1的线段上色有很多方法,再给长度1的线段上色又有很多方法)。长度为3的线段,有a[3]个方案来上色(1、直接给长度为3个线段上色,有若干个方案。 2、先给长度为2的线段上色,再给长度为1的线段上色。3、给长度为1的线段上色,再给长度为2个线段上色。 4、分3次,给3个长度为1的线段上色)


现在知道了a[1]....a[n]


问你,直接给长度为n的线段上色的方案总数。


结果可以递推……递推公式f[i] = a[i] - sum(f[j] * a[i-j]),和上面的公式一样……(毕竟本来也就是一道题嘛~ 只不过把长度为k列的方案总数,改为装饰方案数了而已)

当n=1的时候,显然答案是 a[1]

当n=2的时候,显然答案是a[2]-a[1]*a[1]. 因为是总方案数,去掉不是直接给长度2上色的方案总数。

当n=3的时候,答案应该是a[3]去掉所有不包含长度3的,总方案数。

莫名的像容斥对不对? 然后我并没有想到怎么容斥……


菊苣告诉我,把n拆分,所有的拆分方案进行容斥。 对于一个拆分方案,如果拆分结果中一共拆成了k份,如果k是偶数,那个把这个拆分方案的总数进行减法运算,否则进行加法运算。


举个例子,3可以拆成1+1+1, 也就是a[1]^3,  3个元素,把ans += a[1]^3

3拆成1+2,,也就是a[1]*a[2],有2个元素,ans-= a[1]*a[2]

3拆成3, 一个元素也就是a[3], ans += a[3]

3拆成2+1,也就是a[2]*a[1], ans -= a[2]*a[1]


正确性我会证明……直接用f[i] = a[i] - sum(f[j] * a[i-j])这个公式来证明就行了,但是这到底怎么想的???!!


好了……

=======

然后回归原题(就是原来的题目啦!)


现在我们只要知道,我们可以穷举所有的列的“贯穿”的情况,然后如果所有的“贯穿”方案中,都没有被横着切,问题就解决了。


至于穷举竖着贯穿的情况,可以直接2^m来穷举所有切割方案,010101……  1表示切割这一列,0表示不动。 然后就可以把矩形切成若干列。


对于一个切割方案,我们想知道他的方案总数,但是这时候要考虑横着切的情况。


这个时候再结合f[i] = s[i] - sum(f[j] * s[i-j])这个递推公式,来解决横着切的方案就行啦~留给读者自己思考了。


其实是这样的…… 对于一个竖着切的切割方案中,我们假设每一块的宽度为a1,a2,a3,a4(假设有4块)


那么我们知道,对于这4块,如果高度为1,他们一定不会被横着切过。

如果高度为2,不被横着切过的方案,可以利用高度为1的求出来。

如果高度为3,可以利用之前求解的结果求出来,这个求解过程类似f[i] = s[i] - sum(f[j] * s[i-j])这个公式……


然后这题就做完了。



这题的容斥原理依然我有疑惑,如果有菊苣看了我的文章,能理解那个地方到底怎么想的,能不能留言或者私信下我……


代码跑了2秒多,差点死。


#include<iostream>#include<cstdio>#include<cstdlib>#include<algorithm>#include<cstring>#include <cmath>#include <cstring>using namespace std;int n, m;long long f[2][1<<17];long long dp[20][20];long long mod=1e9+7;/*long long dp(int n, int m){if (n<m)swap(n, m);int cur=0;memset(f,0,sizeof(f));//cout<< (1<<m) << endl;f[cur][(1<<m) - 1] = 1;for (int i = 0; i < n; ++ i){for (int j = 0; j < m ; ++ j){cur^=1;memset(f[cur], 0, sizeof(f[cur]));for (int k = 0; k < (1<<m); ++ k){if (j && !(k & (1<<j-1)) && (k&(1<<j))){f[cur][k | (1<<j-1)] += f[cur^1][k];f[cur][k | (1<<j-1)] %= mod;}f[cur][k ^ (1<<j)] += f[cur^1][k];f[cur][k ^ (1<<j)] %= mod;}}}return f[cur][(1<<m)-1];}*/void doit(){if (n<m)swap(n, m);long long q[100];long long g[100];long long ans=0;for (int i = 0; i < (1<<(m-1)); ++ i){int count=0;//总数量int size=1;for (int j=0;j<m-1;++j)if (i&(1<<j)){q[count++]=size;size=1;}else size++;q[count++]=size;//记录这个分配方案中,一共分了countk块,每块的宽度为q[i]//下面要进行递推,算出方案没有行分列的方案数量for (int j = 1; j <= n; ++ j){g[j] = 1;for (int k = 0; k != count; ++ k)g[j] = g[j] * dp[q[k]][j] % mod;for (int k =1; k < j; ++ k){long long cnt = 1;for (int num=0; num != count; ++ num)cnt = cnt * dp[q[num]][j-k] % mod;g[j] = (g[j] - cnt*g[k] + mod) % mod;}}if (count %2)ans = (ans + g[n]) % mod;else ans = (ans - g[n] + mod) % mod;}printf("%lld\n", ans);}void init();int main(){init();while (~scanf("%d%d", &n, &m)){doit();}return 0;}void init(){dp[1][1] = 0;dp[1][2] = 1;dp[1][3] = 0;dp[1][4] = 1;dp[1][5] = 0;dp[1][6] = 1;dp[1][7] = 0;dp[1][8] = 1;dp[1][9] = 0;dp[1][10] = 1;dp[1][11] = 0;dp[1][12] = 1;dp[1][13] = 0;dp[1][14] = 1;dp[1][15] = 0;dp[1][16] = 1;dp[2][1] = 1;dp[2][2] = 2;dp[2][3] = 3;dp[2][4] = 5;dp[2][5] = 8;dp[2][6] = 13;dp[2][7] = 21;dp[2][8] = 34;dp[2][9] = 55;dp[2][10] = 89;dp[2][11] = 144;dp[2][12] = 233;dp[2][13] = 377;dp[2][14] = 610;dp[2][15] = 987;dp[2][16] = 1597;dp[3][1] = 0;dp[3][2] = 3;dp[3][3] = 0;dp[3][4] = 11;dp[3][5] = 0;dp[3][6] = 41;dp[3][7] = 0;dp[3][8] = 153;dp[3][9] = 0;dp[3][10] = 571;dp[3][11] = 0;dp[3][12] = 2131;dp[3][13] = 0;dp[3][14] = 7953;dp[3][15] = 0;dp[3][16] = 29681;dp[4][1] = 1;dp[4][2] = 5;dp[4][3] = 11;dp[4][4] = 36;dp[4][5] = 95;dp[4][6] = 281;dp[4][7] = 781;dp[4][8] = 2245;dp[4][9] = 6336;dp[4][10] = 18061;dp[4][11] = 51205;dp[4][12] = 145601;dp[4][13] = 413351;dp[4][14] = 1174500;dp[4][15] = 3335651;dp[4][16] = 9475901;dp[5][1] = 0;dp[5][2] = 8;dp[5][3] = 0;dp[5][4] = 95;dp[5][5] = 0;dp[5][6] = 1183;dp[5][7] = 0;dp[5][8] = 14824;dp[5][9] = 0;dp[5][10] = 185921;dp[5][11] = 0;dp[5][12] = 2332097;dp[5][13] = 0;dp[5][14] = 29253160;dp[5][15] = 0;dp[5][16] = 366944287;dp[6][1] = 1;dp[6][2] = 13;dp[6][3] = 41;dp[6][4] = 281;dp[6][5] = 1183;dp[6][6] = 6728;dp[6][7] = 31529;dp[6][8] = 167089;dp[6][9] = 817991;dp[6][10] = 4213133;dp[6][11] = 21001799;dp[6][12] = 106912793;dp[6][13] = 536948224;dp[6][14] = 720246619;dp[6][15] = 704300462;dp[6][16] = 289288426;dp[7][1] = 0;dp[7][2] = 21;dp[7][3] = 0;dp[7][4] = 781;dp[7][5] = 0;dp[7][6] = 31529;dp[7][7] = 0;dp[7][8] = 1292697;dp[7][9] = 0;dp[7][10] = 53175517;dp[7][11] = 0;dp[7][12] = 188978103;dp[7][13] = 0;dp[7][14] = 124166811;dp[7][15] = 0;dp[7][16] = 708175999;dp[8][1] = 1;dp[8][2] = 34;dp[8][3] = 153;dp[8][4] = 2245;dp[8][5] = 14824;dp[8][6] = 167089;dp[8][7] = 1292697;dp[8][8] = 12988816;dp[8][9] = 108435745;dp[8][10] = 31151234;dp[8][11] = 940739768;dp[8][12] = 741005255;dp[8][13] = 164248716;dp[8][14] = 498190405;dp[8][15] = 200052235;dp[8][16] = 282756494;dp[9][1] = 0;dp[9][2] = 55;dp[9][3] = 0;dp[9][4] = 6336;dp[9][5] = 0;dp[9][6] = 817991;dp[9][7] = 0;dp[9][8] = 108435745;dp[9][9] = 0;dp[9][10] = 479521663;dp[9][11] = 0;dp[9][12] = 528655152;dp[9][13] = 0;dp[9][14] = 764896039;dp[9][15] = 0;dp[9][16] = 416579196;dp[10][1] = 1;dp[10][2] = 89;dp[10][3] = 571;dp[10][4] = 18061;dp[10][5] = 185921;dp[10][6] = 4213133;dp[10][7] = 53175517;dp[10][8] = 31151234;dp[10][9] = 479521663;dp[10][10] = 584044562;dp[10][11] = 472546535;dp[10][12] = 732130620;dp[10][13] = 186229290;dp[10][14] = 274787842;dp[10][15] = 732073997;dp[10][16] = 320338127;dp[11][1] = 0;dp[11][2] = 144;dp[11][3] = 0;dp[11][4] = 51205;dp[11][5] = 0;dp[11][6] = 21001799;dp[11][7] = 0;dp[11][8] = 940739768;dp[11][9] = 0;dp[11][10] = 472546535;dp[11][11] = 0;dp[11][12] = 177126748;dp[11][13] = 0;dp[11][14] = 513673802;dp[11][15] = 0;dp[11][16] = 881924366;dp[12][1] = 1;dp[12][2] = 233;dp[12][3] = 2131;dp[12][4] = 145601;dp[12][5] = 2332097;dp[12][6] = 106912793;dp[12][7] = 188978103;dp[12][8] = 741005255;dp[12][9] = 528655152;dp[12][10] = 732130620;dp[12][11] = 177126748;dp[12][12] = 150536661;dp[12][13] = 389322891;dp[12][14] = 371114062;dp[12][15] = 65334618;dp[12][16] = 119004311;dp[13][1] = 0;dp[13][2] = 377;dp[13][3] = 0;dp[13][4] = 413351;dp[13][5] = 0;dp[13][6] = 536948224;dp[13][7] = 0;dp[13][8] = 164248716;dp[13][9] = 0;dp[13][10] = 186229290;dp[13][11] = 0;dp[13][12] = 389322891;dp[13][13] = 0;dp[13][14] = 351258337;dp[13][15] = 0;dp[13][16] = 144590622;dp[14][1] = 1;dp[14][2] = 610;dp[14][3] = 7953;dp[14][4] = 1174500;dp[14][5] = 29253160;dp[14][6] = 720246619;dp[14][7] = 124166811;dp[14][8] = 498190405;dp[14][9] = 764896039;dp[14][10] = 274787842;dp[14][11] = 513673802;dp[14][12] = 371114062;dp[14][13] = 351258337;dp[14][14] = 722065660;dp[14][15] = 236847118;dp[14][16] = 451896972;dp[15][1] = 0;dp[15][2] = 987;dp[15][3] = 0;dp[15][4] = 3335651;dp[15][5] = 0;dp[15][6] = 704300462;dp[15][7] = 0;dp[15][8] = 200052235;dp[15][9] = 0;dp[15][10] = 732073997;dp[15][11] = 0;dp[15][12] = 65334618;dp[15][13] = 0;dp[15][14] = 236847118;dp[15][15] = 0;dp[15][16] = 974417347;dp[16][1] = 1;dp[16][2] = 1597;dp[16][3] = 29681;dp[16][4] = 9475901;dp[16][5] = 366944287;dp[16][6] = 289288426;dp[16][7] = 708175999;dp[16][8] = 282756494;dp[16][9] = 416579196;dp[16][10] = 320338127;dp[16][11] = 881924366;dp[16][12] = 119004311;dp[16][13] = 144590622;dp[16][14] = 451896972;dp[16][15] = 974417347;dp[16][16] = 378503901;}





0 0