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 ...... hNhN

Output

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 1

Sample Output 1 Copy

Copy
12800

One of the ways to paint the squares is shown below:

  ###  ####  #
#### ###
#########


Sample Input 2 Copy

Copy
2
2 2

Sample Output 2 Copy

Copy
6

There are six ways to paint the squares, as follows:

## ## ## ## ## ##
## ## ## ## ## ##


Sample Input 3 Copy

Copy
5
2 1 2 1 2

Sample Output 3 Copy

Copy
256

Every way to paint the squares satisfies the condition.


Sample Input 4 Copy

Copy
9
27 18 28 18 28 45 90 45 23

Sample Output 4 Copy

Copy
844733013

Remember to print the number of ways modulo 109+7109+7.

按照题目的要求,四个字符组成的正方形区域内两种颜色要各占一半。
先看一个例子

2

3 3

图案为

##

##

##

方案有这么几种(两种字符代表两种颜色)

|*#|#*|#*|*#|*#|#*|*#|#*|** |##

|#*|*#|*#|*#|*#|#*|#*|#*|##|**

|*#|#*|*#|#*|*#|#*|#*|*#|** |##

一共十种方案

可以总结的规律是如果一列中的颜色没有连续相同的,比如第1,2,9,10种方案,那么在第一列确定的情况下,第二列还可以有两种方案,但是一旦有连续相同的了,比如第k和k+1颜色相同,那么在第二列的k和k+1(如果存在的话)颜色就是已经确定的了,这样其他位置的颜色也是确定的,所以只有一种方案。如此就可以分开来存储有连续相同的方案数,和交替颜色(无连续相同)的方案数。

用dp[i][0]存无连续相同的方案数。而dp[i][j]分两种情况。

由于每一列高度不尽相同,还有考虑各种情况。

对于每一列,求无连续相同颜色的方案,只是局限于其与前一列接触的部分,不接触的部分颜色可以随意设置,至于下一列是否会接触这一部分再又下一列去选择。

dp[i][j]呢,对于与前一列有接触的部分,dp[i][j]存 有连续相同的方案数,假如这一列比前一列高出d个,那么dp[i][j] = dp[i - 1][j] * 2 ^ d,对于高出的部分是很灵活的,不会受前一列的限制,可以随意变化,至于高出来这一块的dp[i][j]存无连续相同的方案数(有连续相同的方案 在底部接触部分已经记录过)。

由于高度可能很大,所以这里采用离散化,把所有的高度存到一个数组里,这样每个列对应一个高度的下标。由于一共有不多于100列,所有最多有100个不相同的高度,直接按照高度差来计算相关量即可。

先看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对应dh中的位置,即第几高的高度
long long dp[101][101];///记录第i列第n块高度往上的方案数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数组 下标从1开始,方便后面dp
    }sort(dh + 1,dh + m + 1);///dh数组排序m = unique(dh + 1,dh + m + 1) - dh - 1;///dh数组离散化去掉重复的高度 m是不相同的高度数for(int i = 1;i <= n;i ++) {hnum[i] = lower_bound(dh + 1,dh + m + 1,h[i]) - dh;///每一列高度在dh数组中对应的位置
    }dp[0][0]=1;///初始化 当第0列有1个无连续相同的方案for(int i = 1;i <= n;i ++) {///对每一列每个高度段进行更新 更新过程为从下往上(dp[i][0] += dp[i - 1][0] * 2 % MOD) %= MOD;///无连续相同方案  加上前i - 1列无连续相同方案数*2 因为可以是与前一列对应位置同色或者异色一共两种方案for(int j = hnum[i] + 1;j <= hnum[i - 1];j ++)///如果前一列比这一列高,高出的部分也存着接触部分无连续相同的方案 但是可能会重复加上上一步的方案数所以下面更新高出的部分时会避免(dp[i][0] += dp[i - 1][j] * 2 % MOD) %= MOD;int d = pow_(2,h[i] - h[i - 1]);///比前一列高出部分的涂色方案数,如果比前一列低 d就等于1for(int j = 1;j <= min(hnum[i - 1],hnum[i]);j ++) {dp[i][j] = dp[i - 1][j] * d % MOD;///有连续相同颜色的方案数 已经分析过接触部分的颜色一定是定下的 所以这一列接触部分有连续相同部分的方案数由高出部分的变化决定 即 乘上d
        }for(int j = hnum[i - 1] + 1;j <= hnum[i];j ++) {///更新比前一列高出的部分 j从上一列的高度加1的下标开始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列无连续方案 * (第j块高度变化方案 -1表示去掉无连续相同方案) * 2 * 剩下几块高度的变化方案数else (dp[1][1] = dp[0][0] * (pow_(2,dh[1]) - 2) % MOD * pow_(2,h[i] - dh[1]) % MOD) %= MOD;///第一列的第一块高度 记录随意变化方案数 -2表示除去dp[i][0]已经记录过的无连续相同方案 勿重复记录
        }}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个无连续相同方案,然后前一列高度为0,所以第一列比前一列高出两个高度块,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个高度块,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,比前一列高出两个高度块,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

转载于:https://www.cnblogs.com/8023spz/p/9406634.html

AtCoder Grand Contest #026 D - Histogram Coloring相关推荐

  1. AtCoder Grand Contest 025 B - RGB Coloring

    B - RGB Coloring 求ax + by = k (0<=x<=n && 0<=y<=n)的方案数,最后乘上C(n, x)*C(n,y) 代码: #i ...

  2. Atcoder Grand Contest 026 (AGC026) F - Manju Game 博弈,动态规划

    原文链接www.cnblogs.com/zhouzhendong/AGC026F.html 前言 太久没有发博客了,前来水一发. 题解 不妨设先手是 A,后手是 B.定义 \(i\) 为奇数时,\(a ...

  3. 【每日亿题#12】AtCoder Grand Contest 021 (A ~ F)全部题解

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 文章目录 AtCoder Grand Contest 021 题解 A. Digit Sum 2 B. ...

  4. AtCoder Grand Contest 008: Contiguous Repainting(思维)

    Contiguous Repainting 时间限制: 2 Sec  内存限制: 256 MB 提交: 69  解决: 22 [提交][状态][讨论版][命题人:admin] 题目描述 There a ...

  5. AtCoder Grand Contest 017

    AtCoder Grand Contest 017 A - Biscuits 有\(n\)个数,问有多少个集合的数的和模\(2\)余\(P\). 随便\(dp\)一下就好了. #include< ...

  6. AtCoder题解——AtCoder Grand Contest 048——A - atcoder < S

    题目相关 题目链接 AtCoder Grand Contest 048 A 题,https://atcoder.jp/contests/agc048/tasks/agc048_a. Problem S ...

  7. AtCoder题解 —— AtCoder Grand Contest 050 —— B - Three Coins —— 动态规划

    题目相关 题目链接 AtCoder Grand Contest 050 B 题,https://atcoder.jp/contests/agc050/tasks/agc050_b. Problem S ...

  8. Atcoder Grand Contest 010 B - Boxes 差分

    B - Boxes 题目连接: http://agc010.contest.atcoder.jp/tasks/agc010_b Description There are N boxes arrang ...

  9. AtCoder Grand Contest 010 D - Decrementing

    题目传送门:https://agc010.contest.atcoder.jp/tasks/agc010_d 题目大意: 有\(n\)个数\(A_i\),它们的\(gcd\)是1,A.B两人轮流操作, ...

最新文章

  1. Rust 数据类型介绍
  2. Android闹钟 AlarmManager的使用
  3. 双指针--Codeforces Round #645 (Div. 2) d题
  4. Couchbase:使用Twitter和Java创建大型数据集
  5. A1137 | 录数据查询模拟
  6. 关于h264bitstream的bug修正及完善
  7. 前端学习 -- HtmlCss -- 表单
  8. 如何获取maven命令执行后成功与否的返回值
  9. word打开老是配置进度_打开word文档显示配置进度怎么办 Word文档提示配置进度解决办法...
  10. graphpad7.04多组比较p值_GraphPad Prism 统计指南 | 什么是P值?
  11. 用java计算_用Java写的计算器
  12. matlab太阳系行星,Matlab动画模拟太阳系行星运动.doc
  13. 编程小知识之时间显示
  14. android otg读写文件,Android USB Host在USB设备OTG中读/写文件
  15. 计算机核心期刊排名及简介一览
  16. 关于MDL的一些事(2)
  17. 牛客--剑指offer,JZ3,JZ4,JZ5,JZ6
  18. 小程序Promise不支持finally解决方案
  19. 雅虎问答将正式关站!
  20. 鸿蒙系统控制LED的实现方法之经典

热门文章

  1. CRM数据库表COM_TA_R3_ID的数据来源
  2. anaconda moviepy_Win10配置anaconda和jupyter
  3. LR录制脚本中文乱码问题
  4. basic和python_PythonBasic
  5. python目标检测答案_你好,这里有一份2019年目标检测指南
  6. python学习-条件语句
  7. c语言编程基础课件,第7章_C语言图形编程基础课件
  8. php tiff,在PHP中将tiff转换为jpg?
  9. EA出品的java射击类游戏,盘点五款射击类RPG游戏:你喜欢这类型游戏吗?
  10. visual studio可以开发python吗_Visual Studio上开发Python六大功能