题目描述

题目传送门

分析

因为有绝对值不好处理,所以我们强制从小到大填数

设 \(f[i][j][p][o]\) 为当前填到了第 \(i\) 个数,波动强度为 \(j\),有 \(p\) 个连续段并且两端的端点选了 \(o\) 个时的概率

注意这里的连续段是强制规定的

那么转移有五种:

\(1\)、填的数单独成为一段并且不在整个区间的两个端点上

\(f[i+1][j-i*2-2][p+1][o]+=f[i][j][p][o]*(p+1-o)\)

因为后面填在这个数两边的数一定比这个数大,所以这个数一定做负贡献

之前一共有 \(p\) 段,可以填的位置有 \(p+1\) 种

因为一个段如果在整个区间的两端的话,只能在它的一边填,还要减去 \(o\)

\(2\)、填的数单独成为一段并且在整个区间的两个端点上

\(f[i+1][j-i-1][p+1][o+1]+=f[i][j][p][o]*(2-o)\)

此时这个数只会做一次负贡献

方案数为剩余的整个区间的端点的数量,即 \(2-o\)

\(3\)、新填的数放在已有的连续段的一端并且不与其它连续段相邻

\(f[i+j][j][p][o]+=f[i][j][p][o]*(p*2-o)\)

因为这个数一定做一次正贡献和一次负贡献,所以会抵消,总贡献不变

每个连续段都有两个端点可以选,再减去已选整个区间的端点的数量

\(4\)、新填的数放在已有的连续段的一端并且与其它连续段相邻

\(f[i+1][j+2*i+2][p-1][o]+=f[i][j][p][o]*(p-1)\)

其实就是把两个端拼成了一个大段

做两次正贡献

\(5\)、新填的数放在已有的连续段的一端并且当前的数填到了整个区间的端点上

\(f[i+1][j+i+1][p][o+1]+=f[i][j][p][o]*(2-o)\)

做一次正贡献

因为题目要求保留的位数不一样

所以,对于精度较低的测试点,可以用 \(double\) 写

对于精度较高的测试点,我们可以手写高精度

手写高精度浮点数其实就是先把整个数左移很多位

然后进行正常的加、乘、除的操作

最后要多少位再四舍五入取到多少位即可

代码

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<iomanip>
#define rg register
const int maxn=105,maxm=8005,bas=2500,jz=10000000;
int n,m,k,mmax;
struct asd{
int num[10],len;
asd(){
memset(num,0,sizeof(num));
len=0;
}
friend asd operator +(const asd &A,const asd &B){
asd C;
C.len=std::max(A.len,B.len);
for(rg int i=0;i<C.len;i++){
C.num[i]+=A.num[i]+B.num[i];
if(C.num[i]>=jz){
C.num[i]-=jz;
C.num[i+1]+=1;
}
}
if(C.num[C.len]) C.len++;
return C;
}
friend asd operator *(const asd &A,const asd &B){
asd C;
for(rg int i=0;i<B.len;i++){
for(rg int j=0;j<A.len;j++){
C.num[i+j]+=B.num[i]*A.num[j];
}
}
for(rg int i=0;i<B.len;i++){
for(rg int j=0;j<A.len;j++){
if(C.num[i+j]>=jz){
C.num[i+j+1]+=C.num[i+j]/jz;
C.num[i+j]%=jz;
}
}
}
C.len=B.len+A.len;
while(C.num[C.len-1]==0 && C.len-1!=0) C.len--;
return C;
}
friend asd operator /(const asd &A,const int B){
asd C,D;
D=A;
for(rg int i=D.len-1;i>=0;i--){
rg int haha=D.num[i]+D.num[i+1]*jz;
C.num[i]=haha/B;
D.num[i]=haha%B;
D.num[i+1]=0;
if(i==0 && D.num[i]>=B/2){
C.num[i]++;
}
if(C.len==0 && C.num[i]){
C.len=i+1;
}
}
while(C.num[C.len-1]==0 && C.len-1!=0) C.len--;
return C;
}
void read(int aa){
len=0;
while(aa){
num[len++]=aa%jz;
aa/=jz;
}
while(num[len-1]==0 && len-1!=0) len--;
}
void write(int aa){
rg int pd=0;
printf("0.");
for(rg int i=len-1;i>=0;i--){
if(aa-7>=0){
if(aa==7 && num[i-1]%1000000%10>=5) pd=1;
printf("%07d",num[i]+pd);
aa-=7;
} else {
if(aa==1 && num[i]/100000%10>=5){
pd=1;
}
if(aa){
printf("%01d",num[i]/1000000%10+pd);
aa--;
}
if(aa==1 && num[i]/10000%10>=5){
pd=1;
}
if(aa){
printf("%01d",num[i]/100000%10+pd);
aa--;
}
if(aa==1 && num[i]/1000%10>=5){
pd=1;
}
if(aa){
printf("%01d",num[i]/10000%10+pd);
aa--;
}
if(aa==1 && num[i]/100%10>=5){
pd=1;
}
if(aa){
printf("%01d",num[i]/1000%10+pd);
aa--;
}
if(aa==1 && num[i]/10%10>=5){
pd=1;
}
if(aa){
printf("%01d",num[i]/100%10+pd);
aa--;
}
if(aa==1 && num[i]%10>=5){
pd=1;
}
if(aa){
printf("%01d",num[i]/10%10+pd);
aa--;
}
if(aa){
printf("%01d",num[i]%10+pd);
aa--;
}
break;
}
}
printf("\n");
}
}g[2][maxm][maxn/2][3];
asd anss;
void solve1(){
mmax=n/2+1;
rg int now=1;
g[0][bas][0][0].num[6]=1;
g[0][bas][0][0].len=7;
for(rg int i=0;i<n;i++){
now^=1;
for(rg int j=0;j<maxm;j++){
for(rg int p=0;p<=mmax;p++){
for(rg int o=0;o<=2;o++){
g[now^1][j][p][o].len=0;
memset(g[now^1][j][p][o].num,0,sizeof(g[now^1][j][p][i].num));
}
}
}
asd haha;
for(rg int j=0;j<maxm;j++){
for(rg int p=0;p<=mmax;p++){
for(rg int o=0;o<=2;o++){
if(g[now][j][p][o].len){
if(j-2*i-2>=0){
haha.read(p+1-o);
g[now^1][j-2*i-2][p+1][o]=g[now^1][j-2*i-2][p+1][o]+g[now][j][p][o]*haha/(i+1);
}
if(o<2 && j-i-1>=0){
haha.read(2-o);
g[now^1][j-i-1][p+1][o+1]=g[now^1][j-i-1][p+1][o+1]+g[now][j][p][o]*haha/(i+1);
}
haha.read(p*2-o);
g[now^1][j][p][o]=g[now^1][j][p][o]+g[now][j][p][o]*haha/(i+1);
if(p && j+2*i+2<maxm){
haha.read(p-1);
g[now^1][j+2*i+2][p-1][o]=g[now^1][j+2*i+2][p-1][o]+g[now][j][p][o]*haha/(i+1);
}
if(o<2 && j+i+1<maxm){
haha.read(2-o);
g[now^1][j+i+1][p][o+1]=g[now^1][j+i+1][p][o+1]+g[now][j][p][o]*haha/(i+1);
}
}
}
}
}
}
for(rg int j=bas+m;j<=bas+(n+1)*n/2;j++){
anss=anss+g[now^1][j][1][2];
}
anss.write(k);
}
double f[2][maxm][maxn/2][3],ans;
void solve2(){
mmax=n/2+1;
rg int now=1;
f[0][bas][0][0]=1.0;
for(rg int i=0;i<n;i++){
now^=1;
for(rg int j=0;j<maxm;j++){
for(rg int p=0;p<=mmax;p++){
for(rg int o=0;o<=2;o++){
f[now^1][j][p][o]=0;
}
}
}
for(rg int j=0;j<maxm;j++){
for(rg int p=0;p<=mmax;p++){
for(rg int o=0;o<=2;o++){
if(f[now][j][p][o]){
if(j-2*i-2>=0) f[now^1][j-2*i-2][p+1][o]+=f[now][j][p][o]*(p+1-o)/(i+1);
if(o<2 && j-i-1>=0) f[now^1][j-i-1][p+1][o+1]+=f[now][j][p][o]*(2-o)/(i+1);
f[now^1][j][p][o]+=f[now][j][p][o]*(p*2-o)/(i+1);
if(p && j+2*i+2<maxm) f[now^1][j+2*i+2][p-1][o]+=f[now][j][p][o]*(p-1)/(i+1);
if(o<2 && j+i+1<maxm) f[now^1][j+i+1][p][o+1]+=f[now][j][p][o]*(2-o)/(i+1);
}
}
}
}
}
for(rg int j=bas+m;j<=bas+(n+1)*n/2;j++){
ans+=f[now^1][j][1][2];
}
std::cout<<std::fixed<<std::setprecision(k)<<ans<<std::endl;
}
int main(){
std::cin>>n>>m>>k;
if(k<=8) solve2();
else solve1();
return 0;
}

题解 洛谷 P2612 【[ZJOI2012]波浪】DP+高精的更多相关文章

  1. 洛谷P4608 [FJOI2016]所有公共子序列问题 【序列自动机 + dp + 高精】

    题目链接 洛谷P4608 题解 建个序列自动机后 第一问暴搜 第二问dp + 高精 设\(f[i][j]\)为两个序列自动机分别走到\(i\)和\(j\)节点的方案数,答案就是\(f[0][0]\) ...

  2. [CEOI2007]树的匹配Treasury(树形DP+高精)

    题意 给一棵树,你可以匹配有边相连的两个点,问你这棵树的最大匹配时多少,并且计算出有多少种最大匹配. N≤1000,其中40%的数据答案不超过 108 题解 显然的树形DP+高精. 这题是作为考试题考 ...

  3. 洛谷1387 二维dp 不是特别简略的题解 智商题

    洛谷1387 dp题目,刚开始写的时候使用了前缀和加搜索,复杂度大概在O(n ^ 3)级别,感觉这么写还是比较对得起普及/提高-的难度的..后来看了题解区各位大神的题解,开始一脸mb,之后备受启发. ...

  4. NOIP2017提高组Day2T2 宝藏 洛谷P3959 状压dp

    原文链接https://www.cnblogs.com/zhouzhendong/p/9261079.html 题目传送门 - 洛谷P3959 题目传送门 - Vijos P2032 题意 给定一个 ...

  5. [洛谷P2597] [ZJOI2012]灾难

    洛谷题目链接:[ZJOI2012]灾难 题目描述 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引 ...

  6. [洛谷P2610] [ZJOI2012]旅游

    洛谷题目链接:[ZJOI2012]旅游 题目描述 到了难得的暑假,为了庆祝小白在数学考试中取得的优异成绩,小蓝决定带小白出去旅游~~ 经过一番抉择,两人决定将T国作为他们的目的地.T国的国土可以用一个 ...

  7. 题解 洛谷P5018【对称二叉树】(noip2018T4)

    \(noip2018\) \(T4\)题解 其实呢,我是觉得这题比\(T3\)水到不知道哪里去了 毕竟我比较菜,不大会\(dp\) 好了开始讲正事 这题其实考察的其实就是选手对D(大)F(法)S(师) ...

  8. 题解 洛谷 P3396 【哈希冲突】(根号分治)

    根号分治 前言 本题是一道讲解根号分治思想的论文题(然鹅我并没有找到论文),正 如论文中所说,根号算法--不仅是分块,根号分治利用的思想和分块像 似却又不同,某一篇洛谷日报中说过,分块算法实质上是一种 ...

  9. 题解-洛谷P4229 某位歌姬的故事

    题面 洛谷P4229 某位歌姬的故事 \(T\) 组测试数据.有 \(n\) 个音节,每个音节 \(h_i\in[1,A]\),还有 \(m\) 个限制 \((l_i,r_i,g_i)\) 表示 \( ...

随机推荐

  1. Mybatis初学经验----------------(2)

    至于myBatis的配置,上篇文章中有,就不说了.今天谈谈myBatis编写Dao层时的用法. 传统Dao层代码需求 1.在Dao层实现类中,存在大量的模板方法,能否提取模板方法,减少我们的工作量. ...

  2. P2346 四子连棋

    P2346 四子连棋 迭代加深++ 题意描述 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗白色棋子,7颗黑色棋子,有两个空白地带,任何一颗黑白棋子都可以向上下左右四个方向移动到相邻的空格,这叫行棋 ...

  3. Dynamic 365 学习(1)

    一 创建解决方案 1.点击下拉菜单 2.找到设置并选择 3.点击解决方案 进入解决方案  该页面会显示你的所有的解决方案  你新建之后的可以在这里进行查看,也可以新增 删除  ... 这里我们先新建一 ...

  4. Pycharm激活码(2020最新永久激活码)

    如果下边的Pycharm激活码过期失效了的话,大家可以关注我的微信公众号:Python联盟,然后回复"激活码"即可获取最新Pycharm永久激活码! 56NPDDVEIV-eyJs ...

  5. Statistical physics approaches to the complex Earth system(相关系统建模理念方法的摘要)

    本文翻译自"Statistical physics approaches to the complex Earth system",其虽然是针对复杂地球系统的统计物理方法的综述,但 ...

  6. ubuntu下安装ESP8266开发环境步骤中可能出现的问题及解决办法

    安装步骤参考如下链接 https://www.jianshu.com/p/e9ce2a60df83 1.在GitHub上拉取代码时发生错误:RPC failed; curl 18 transfer c ...

  7. 内网渗透 day13-漏洞复现

    漏洞复现 目录 1. 永恒之蓝(445端口) 2. 手动微笑漏洞(21端口 vsftpd2.3.4版本) 3. ingres数据库DBMS后门(1524端口) 4. distcc漏洞(3632) 5. ...

  8. 《Python3反爬虫原理与绕过实战》作者韦世东

    可以用(k1,k2)-k1来设置,如果有重复的key,则保留key1,舍弃key2/打印appleMap{1=Apple{id=1,name=苹果1,money=3.25,num=10},2=Appl ...

  9. springboot linux打包后访问不到resources 下面的模板文件

    在本地是可以直接获取模板文件并下载,但是服务器上就不行 本地代码: @Overridepublic void downArchRelayTemplate(HttpServletRequest requ ...

  10. spring cloud 入门系列

    springcloud入门总结转发自:https://www.cnblogs.com/sam-uncle/p/9340390.html 最近看到微服务很火,也是未来的趋势, 所以就去学习下,在dubb ...