jzoj. 3505. 【NOIP2013模拟11.4A组】积木(brick)
来源:互联网 发布:炒股模拟软件app 编辑:程序博客网 时间:2024/06/05 09:23
Description
小A正在搭积木。有N个位置可以让小A使用,初始高度都为0。小A每次搭积木的时候,都会选定一个拥有相同高度的区间[A..B],然后将位置[A+1..B-1]上的所有积木的高度加一。不幸的是,小A把积木搭好之后没多久,小A调皮的弟弟就将其中若干个位置上的积木弄倒了。小A想知道他原来的积木是如何摆放的,所以他求助于你,请你告诉他原来有多少种可能的摆法。
Input
第一行为一个正整数N,表示小A有N个位置。
第二行有N个由空格分隔的整数Hi,表示第i个位置的积木高度。-1表示这个位置上的积木已经被弄倒了。
Output
唯一的一行,输出包括可能的摆法mod 1,000,000,007的结果。
Sample Input
输入1:
3
-1 2 -1
输入2:
-1 -1 -1
输入3:
6
-1 -1 -1 2 -1 -1
Sample Output
输出1:
0
输出2:
2
输出3:
3
Data Constraint
对于50%的数据 1<=N<=1000 -1<=Hi<=1000
对于80%的数据 1<=N<=10000
对于100%的数据 1<=N<=20000 -1<=Hi<=10000
分析:
(水解):
设f[i,j]为第i个数,高度为j的方案数,有
f[i,j]=sum(f[i-1,j-1],f[i-1,j],f[i-1,j+1])
如果a[i]没有被破坏,那就除f[i,a[i]]外的状态都不合法。
暴力跑一边,会超一点时。把每次mod,改为统计10次取一次mod就不会超时了。
(正解):对于每两个有确定高度的点,即a[i]≠-1(或者是两端的0),考虑中间的方案数。
设a[i]和a[j]≠-1,则
对于集合
{a[i],a[i+1],a[i+2],……a[j]}
因为相邻两个数的差不超过1,则得到集合
{a[i+1]-a[i],a[i+2]-a[i],……a[j]-a[j-1]}
这个集合的每个元素的值只可能是-1,0,1,且这些元素的和为sum=a[j]-a[i]。
如果sum>0,删去其中sum个1,剩余元素和为0;
如果sum<0,删去其中 |sum| 个-1,剩余原始和为0;
其实这两种状态时等价的。
这时我们得到了一个和为0的集合。
设i到j中间有m个元素,其中1有x个,则-1有x个,0就是有(m-2x-sum)个(其实这个不重要)。
那方案数为C(m,sum+x)*C(m-sum-x,x)
{中间有m个空位,1有sum+x个;对于剩余的m-sum-x个位置,-1有x个;剩余的位置都是0,方案显然是1,相乘结果不变}
我们应该先预处理出n! (当然要取mod啦),然后每次运算都有求组合数,以为要除以某些已经mod了的数,要预处理出n!的逆元。因为mod p(p为质数),可以用费马小定理或欧拉定理得到。
(n!)^(-1)=(n!)^(p-2)
代码(水解):
const modd=1000000007;var f:array [0..1,-1..20001] of int64; a,max:array [0..20001] of longint; n,i,j,x,s,t,m,y:longint;begin assign(input,'brick.in'); assign(output,'brick.out'); reset(input); rewrite(output); readln(n); for i:=1 to n do read(a[i]); if a[1]>0 then begin writeln(0); close(input); close(output); exit; end; m:=n div 2+1; for i:=1 to n do if i<m then max[i]:=i-1 else max[i]:=n-i; x:=0; f[x,0]:=1; for i:=2 to n do begin y:=x; x:=1-x; fillchar(f[x],sizeof(f[x]),0); if a[i]=-1 then begin if i mod 10=0 then for j:=0 to max[i] do f[x,j]:=(f[y,j-1]+f[y,j]+f[y,j+1])mod modd else for j:=0 to max[i] do f[x,j]:=f[y,j-1]+f[y,j]+f[y,j+1]; end else f[x,a[i]]:=(f[y,a[i]-1]+f[y,a[i]]+f[y,a[i]+1])mod modd; end; writeln(f[x,0] mod modd); close(input); close(output);end.
代码(正解)(by:jzoj某大神,本人仅转载):
const mo=1000000007;var n,i,j,k,l,h:longint; a:array[1..20000]of longint; jc,ny:array[0..20000]of longint; ans,tot:longint;function ksm(x,y:longint):longint;begin if y=1 then exit(x); ksm:=ksm(x,y>>1);ksm:=int64(ksm)*ksm mod mo; if y and 1=1 then ksm:=int64(ksm)*x mod mo;end;function c(a,b:longint):longint;begin if a>b then exit(0); exit(int64(jc[b])*ny[a]mod mo*ny[b-a]mod mo);end;begin assign(input,'brick.in');reset(input); assign(output,'brick.out');rewrite(output); readln(n);for i:=1 to n do read(a[i]); jc[0]:=1;for i:=1 to n do jc[i]:=int64(jc[i-1])*i mod mo; ny[n]:=ksm(jc[n],mo-2);for i:=n-1 downto 0 do ny[i]:=int64(ny[i+1])*(i+1)mod mo; if(a[1]>0)or(a[n]>0)then begin writeln(0);halt; end; a[1]:=0;a[n]:=0;i:=1;j:=1;ans:=1; while i<n do begin inc(i);if a[i]>-1 then begin tot:=0;h:=abs(a[i]-a[j]); for k:=0 to i-j-h do begin l:=i-j-k;if (l+h)and 1=1 then continue; tot:=(tot+int64(c(k,i-j))*(c((l+h)>>1,l)-c((l+a[i]+a[j]+2)>>1,l))mod mo+mo)mod mo; end; ans:=int64(tot)*ans mod mo;j:=i; end; end; writeln(ans);end.
- jzoj. 3505. 【NOIP2013模拟11.4A组】积木(brick)
- JZOJ 3505. 【NOIP2013模拟11.4A组】积木(brick)
- [jzoj]3505. 【NOIP2013模拟11.4A组】积木(brick) (排列组合vsDP)
- 【NOIP2013模拟11.4A组】积木(brick)
- 高中OJ3505. 【NOIP2013模拟11.4A组】积木(brick)
- JZOJ 3506. 【NOIP2013模拟11.4A组】善良的精灵
- JZOJ 3506. 【NOIP2013模拟11.4A组】善良的精灵
- jzoj. 3518. 【NOIP2013模拟11.6A组】进化序列(evolve)
- JZOJ 3518. 【NOIP2013模拟11.6A组】进化序列(evolve)
- JZOJ 3526. 【NOIP2013模拟11.7A组】不等式(solve)
- jzoj. 3526. 【NOIP2013模拟11.7A组】不等式(solve)
- JZOJ-senior-3502. 【NOIP2013模拟11.4B组】方格游戏
- 【NOIP2013模拟11.4A组】游乐场
- jzoj. 3523. 【NOIP2013模拟11.7A组】JIH的玩偶(tree)
- jzoj. 3519. 【NOIP2013模拟11.6A组】灵能矩阵(pylon)
- [jzoj]3526. 【NOIP2013模拟11.7A组】不等式(solve)(类欧几里得)
- [jzoj]3503. 【NOIP2013模拟11.4B组】粉刷(paint)(位运算优化)
- jzoj 3520. 【NOIP2013模拟11.7B组】原根(math)
- (63)ListIterator用法、List均有的增删改查
- leetcode 70. Climbing Stairs
- 爬取妹子图(python):爬虫(bs+rq)+ gevent多线程
- Mybatis逆向生成文件
- 【机房重构】-C#注册
- jzoj. 3505. 【NOIP2013模拟11.4A组】积木(brick)
- 关于UITextField左侧图标的设置
- UVa401-Palindromes-回文词-字符函数,常量数组
- poj 2588
- android之服务service远程服务
- webpack+vue 实现多页面开发
- 05.15 三剑客之老四find命令详解
- dva -react TypeError: root.findRouters(...).getRouterInfo is not a function
- 关于在Windows10 Eclipse 配置Dos(cmd)窗口