Compute's Wallpaper
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 1048576K,其他语言2097152K
64bit IO Format: %lld
题目描述
Compute 买了台新电脑,他的初始壁纸是自带的风景壁纸,但他更喜欢小姐姐。
现在 CSL 连续 n 天每天给 Compute 一张小姐姐照片,第 i 张的小姐姐对 Compute 有 \(a_i\) 的吸引力。Compute 可以选择在这天换上 CSL 当天发给他的壁纸,并至少连续使用 \(a_i\) 天。
但我们都知道,每张壁纸的吸引力都会日益衰减,具体来说,当前壁纸每天对他的吸引力都会衰减 1。当衰减到 0 之后,Compute 就有可能换掉它,或者也有可能在之后的某天才换掉它,甚至不换一直用下去。
比如说,在第 1 天,CSL 发了一张吸引力为 2 的小姐姐壁纸给他并且他使用了这张壁纸;那么第 2 天,这张壁纸的吸引力就会减为 1 ,他肯定不会更换壁纸;但到了第 3 天,这张壁纸的吸引力减为 0,他可以选择更换为另一个壁纸或继续使用原来那张壁纸。
Compute 想知道,这 n 天他的桌面壁纸至少出现过两张不同的小姐姐的方案有多少种。
由于这个数可能很大,你只需要输出它对 \(10^9+7\) 取余后的结果即可。
输入描述
第一行有一个整数 \(n(2\leq n \leq 10^6) \),表示 CSL 给 Compute 发壁纸的天数。
第二行有 n 个整数 \(a_1, a_2, \ldots, a_n (0 \leq a_i \leq 100)\),分别表示第 i 天 CSL 给 Compute 发的小姐姐壁纸的吸引力为 \(a_i\)
。输出描述
在一行输出一个正整数,表示 Compute 桌面壁纸至少出现过两张不同的小姐姐的方案数对 \(10^9+7\)
取余后的结果。
样例
输入样例1
1 2 |
3 1 2 3 |
输出样例1
1 |
2 |
说明
对于第一个样例,Compute 有两种更换壁纸的方案:第 1 天和第 2 天换壁纸;第 1 天和第 3 天换壁纸。
输入样例2
1 2 |
6 1 1 4 5 1 4 |
输出样例2
1 |
17 |
输入样例3
1 2 |
7 1 9 1 9 8 1 0 |
输出样例3
1 |
18 |
输入样例4
1 2 |
9 8 2 0 2 3 3 0 1 6 |
输出样例4
1 |
64 |
输入样例5
1 2 |
30 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 |
输出样例5
1 |
73741786 |
备注
Compute 可以在 CSL 发完壁纸的 n 天后继续使用他所正在使用最后的一张壁纸。
题解
线段树优化dp。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
#include <cstdio> #include <iostream> #define Mod 1000000007 using namespace std; const int N = 1000009; int f[4*N], n, a[N]; void update(int l, int r, int rt, int p, int v) { if(r<p || l>p || l>r) return; if(l==r) { f[rt] = v; return; } int mid = (l + r) >> 1, lc = rt << 1, rc = rt << 1 | 1; if(mid>=p) update(l, mid, lc, p, v); else update(mid+1, r, rc, p, v); f[rt] = (f[lc] + f[rc]) % Mod; } int query(int l, int r, int rt, int L, int R) { if(l>R || r<L || l>r || L>R) return 0; if(L<=l && r<=R) return f[rt]; int mid = (l + r) >> 1, lc = rt << 1, rc = rt << 1 | 1; int lv = query(l, mid, lc, L, R); int rv = query(mid+1, r, rc, L, R); f[rt] = (f[lc] + f[rc]) % Mod; return (lv + rv) % Mod; } int main(int argc, char const *argv[]) { scanf("%d", &n); for(int i = 1; i <= n; i++) scanf("%d", &a[i]); for(int i = n; i > 0; i--) { int l = i + a[i] + (a[i]==0); if(l>n) continue; int tmp = query(1, n, 1, l, n); update(1, n, 1, i, n-l+1+tmp); } printf("%d\n", f[1]); return 0; } |
叨叨几句... NOTHING