AtCoder Grand Contest #026 D - Histogram Coloring
Time Limit: 2 sec / Memory Limit: 1024 MB
Score :?11001100?points
Problem Statement
Let us consider a grid of squares with?109109?rows and?NN?columns. Let?(i,j)(i,j)?be the square at the?ii-th column?(1≤i≤N)(1≤i≤N)?from the left and?jj-th row?(1≤j≤109)(1≤j≤109)?from the bottom.
Snuke has cut out some part of the grid so that, for each?i=1,2,...,Ni=1,2,...,N, the bottom-most?hihi?squares are remaining in the?ii-th column from the left. Now, he will paint the remaining squares in red and blue. Find the number of the ways to paint the squares so that the following condition is satisfied:
- Every remaining square is painted either red or blue.
- For all?1≤i≤N?11≤i≤N?1?and?1≤j≤min(hi,hi+1)?11≤j≤min(hi,hi+1)?1, there are exactly two squares painted red and two squares painted blue among the following four squares:?(i,j),(i,j+1),(i+1,j)(i,j),(i,j+1),(i+1,j)?and?(i+1,j+1)(i+1,j+1).
Since the number of ways can be extremely large, print the count modulo?109+7109+7.
Constraints
- 1≤N≤1001≤N≤100
- 1≤hi≤1091≤hi≤109
Input
Input is given from Standard Input in the following format:
NN h1h1 h2h2 ...... hNhNOutput
Print the number of the ways to paint the squares, modulo?109+7109+7.
Sample Input 1?Copy
Copy 9 2 3 5 4 1 2 4 2 1Sample Output 1?Copy
Copy 12800One of the ways to paint the squares is shown below:
### #### # #### ### #########Sample Input 2?Copy
Copy 2 2 2Sample Output 2?Copy
Copy 6There are six ways to paint the squares, as follows:
## ## ## ## ## ## ## ## ## ## ## ##Sample Input 3?Copy
Copy 5 2 1 2 1 2Sample Output 3?Copy
Copy 256Every way to paint the squares satisfies the condition.
Sample Input 4?Copy
Copy 9 27 18 28 18 28 45 90 45 23Sample Output 4?Copy
Copy 844733013Remember to print the number of ways modulo?109+7109+7.
?
按照題目的要求,四個(gè)字符組成的正方形區(qū)域內(nèi)兩種顏色要各占一半。
先看一個(gè)例子
2
3 3
圖案為
##
##
##
方案有這么幾種(兩種字符代表兩種顏色)
|*#|#*|#*|*#|*#|#*|*#|#*|** |##
|#*|*#|*#|*#|*#|#*|#*|#*|##|**
|*#|#*|*#|#*|*#|#*|#*|*#|** |##
一共十種方案
可以總結(jié)的規(guī)律是如果一列中的顏色沒有連續(xù)相同的,比如第1,2,9,10種方案,那么在第一列確定的情況下,第二列還可以有兩種方案,但是一旦有連續(xù)相同的了,比如第k和k+1顏色相同,那么在第二列的k和k+1(如果存在的話)顏色就是已經(jīng)確定的了,這樣其他位置的顏色也是確定的,所以只有一種方案。如此就可以分開來存儲(chǔ)有連續(xù)相同的方案數(shù),和交替顏色(無連續(xù)相同)的方案數(shù)。
用dp[i][0]存無連續(xù)相同的方案數(shù)。而dp[i][j]分兩種情況。
由于每一列高度不盡相同,還有考慮各種情況。
對于每一列,求無連續(xù)相同顏色的方案,只是局限于其與前一列接觸的部分,不接觸的部分顏色可以隨意設(shè)置,至于下一列是否會(huì)接觸這一部分再又下一列去選擇。
dp[i][j]呢,對于與前一列有接觸的部分,dp[i][j]存 有連續(xù)相同的方案數(shù),假如這一列比前一列高出d個(gè),那么dp[i][j] = dp[i - 1][j] * 2 ^ d,對于高出的部分是很靈活的,不會(huì)受前一列的限制,可以隨意變化,至于高出來這一塊的dp[i][j]存無連續(xù)相同的方案數(shù)(有連續(xù)相同的方案 在底部接觸部分已經(jīng)記錄過)。
由于高度可能很大,所以這里采用離散化,把所有的高度存到一個(gè)數(shù)組里,這樣每個(gè)列對應(yīng)一個(gè)高度的下標(biāo)。由于一共有不多于100列,所有最多有100個(gè)不相同的高度,直接按照高度差來計(jì)算相關(guān)量即可。
先看c++代碼:
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std;const int MOD = (int)1e9 + 7;int n,m,h[101],hnum[101],dh[101];///h記錄每一列高度 dh記錄離散化后的各不相同的高度 hnum記錄h對應(yīng)dh中的位置,即第幾高的高度 long long dp[101][101];///記錄第i列第n塊高度往上的方案數(shù)int pow_(long long x,int y) {///快速冪求 x的y次方long long ans = 1;if(y > 0) {while(y) {if(y % 2)ans = ans * x % MOD;x = x * x % MOD;y /= 2;}}return ans; }int main() {scanf("%d",&n);for(int i = 1;i <= n;i ++) {scanf("%d",&h[i]);dh[++ m] = h[i];///先把高度存到dh數(shù)組 下標(biāo)從1開始,方便后面dp }sort(dh + 1,dh + m + 1);///dh數(shù)組排序m = unique(dh + 1,dh + m + 1) - dh - 1;///dh數(shù)組離散化去掉重復(fù)的高度 m是不相同的高度數(shù)for(int i = 1;i <= n;i ++) {hnum[i] = lower_bound(dh + 1,dh + m + 1,h[i]) - dh;///每一列高度在dh數(shù)組中對應(yīng)的位置 }dp[0][0]=1;///初始化 當(dāng)?shù)?列有1個(gè)無連續(xù)相同的方案for(int i = 1;i <= n;i ++) {///對每一列每個(gè)高度段進(jìn)行更新 更新過程為從下往上(dp[i][0] += dp[i - 1][0] * 2 % MOD) %= MOD;///無連續(xù)相同方案 加上前i - 1列無連續(xù)相同方案數(shù)*2 因?yàn)榭梢允桥c前一列對應(yīng)位置同色或者異色一共兩種方案for(int j = hnum[i] + 1;j <= hnum[i - 1];j ++)///如果前一列比這一列高,高出的部分也存著接觸部分無連續(xù)相同的方案 但是可能會(huì)重復(fù)加上上一步的方案數(shù)所以下面更新高出的部分時(shí)會(huì)避免(dp[i][0] += dp[i - 1][j] * 2 % MOD) %= MOD;int d = pow_(2,h[i] - h[i - 1]);///比前一列高出部分的涂色方案數(shù),如果比前一列低 d就等于1for(int j = 1;j <= min(hnum[i - 1],hnum[i]);j ++) {dp[i][j] = dp[i - 1][j] * d % MOD;///有連續(xù)相同顏色的方案數(shù) 已經(jīng)分析過接觸部分的顏色一定是定下的 所以這一列接觸部分有連續(xù)相同部分的方案數(shù)由高出部分的變化決定 即 乘上d }for(int j = hnum[i - 1] + 1;j <= hnum[i];j ++) {///更新比前一列高出的部分 j從上一列的高度加1的下標(biāo)開始if(j > 1)(dp[i][j] = dp[i - 1][0] * (pow_(2,dh[j] - dh[j - 1]) - 1) % MOD * 2 % MOD * pow_(2,h[i] - dh[j]) % MOD) %= MOD;///一般情況 前i - 1列無連續(xù)方案 * (第j塊高度變化方案 -1表示去掉無連續(xù)相同方案) * 2 * 剩下幾塊高度的變化方案數(shù)else (dp[1][1] = dp[0][0] * (pow_(2,dh[1]) - 2) % MOD * pow_(2,h[i] - dh[1]) % MOD) %= MOD;///第一列的第一塊高度 記錄隨意變化方案數(shù) -2表示除去dp[i][0]已經(jīng)記錄過的無連續(xù)相同方案 勿重復(fù)記錄 }}long long ans = 0;for(int i = 0;i <= hnum[n];i++)(ans += dp[n][i]) %= MOD;printf("%lld",ans);return 0; } View Code?
### #### # #### ### #########
對于樣例一來說,最初dp[0][0] = 1;dh[] = {0,1,2,3,4,5},hnum[] = {0,2,3,5,4,1,2,4,2,1},然后一列一列來
第一列:dp[1][0] = dp[0][0] * 2 = 2,2個(gè)無連續(xù)相同方案,然后前一列高度為0,所以第一列比前一列高出兩個(gè)高度塊,dp[1][1] = 0,dp[1][2] = 2;
第二列:dp[2][0] = dp[1][0] * 2 = 4,dp[2][1] = dp[1][1] * 2 = 0,dp[2][2] = dp[1][2] * 2 = 4;比前一列高出3 - 2 = 1個(gè)高度塊,dp[2][3] = 4;
第三列:dp[3][0] = dp[2][0] * 2 = 8,dp[3][1] = dp[2][1] * 4 = 0,dp[3][2] = dp[2][2] * 4 = 16,dp[3][3] = dp[2][3] * 4 = 16,比前一列高出兩個(gè)高度塊,dp[3][4] = dp[2][0] * 2 * 2 = 16,dp[3][5] = 8;
第四列:dp[4][0] = dp[3][0] * 2 + dp[3][5] * 2 = 32,dp[4][1] = 0,dp[4][2] = dp[3][2] = 16,dp[4][3] = 16,dp[4][4] = 16;
第五列:dp[5][0] = dp[4][0] * 2 + dp[4][2] * 2 + dp[4][3] * 2 + dp[4][4] * 2 = 160,dp[5][1] = 0;
第六列:dp[6][0] = dp[5][0] * 2 = 320,dp[6][1] = 0,dp[6][2] = dp[5][0] * 2 = 320;
第七列:dp[7][0] = dp[6][0] * 2 = 640,dp[7][1] = 0,dp[7][2] = dp[6][2] * 4 = 1280,dp[7][3] = dp[6][0] * 2 * 2 = 1280,dp[7][4] = dp[6][0] * 2 = 640;
第八列:dp[8][0] = dp[7][0] * 2 + dp[7][3] * 2 + dp[7][4] * 2 = 5120,dp[8][1] = 0,dp[8][2] = dp[7][2] = 1280;
第九列:dp[9][0] = dp[8][0] * 2 + dp[8][2] * 2 = 12800,dp[9][1] = 0;
答案:12800
轉(zhuǎn)載于:https://www.cnblogs.com/8023spz/p/9406634.html
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的AtCoder Grand Contest #026 D - Histogram Coloring的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Oracle if else if f
- 下一篇: 线段树(结构体建法_QAQ)