前赤壁赋

  壬戌之秋,七月既望,苏子与客泛舟游于赤壁之下。清风徐来,水波不兴。举酒属客,诵明月之诗,歌窈窕之章。少焉,月出于东山之上,徘徊于斗牛之间。白露横江,水光接天。纵一苇之所如,凌万顷之茫然。浩浩乎如冯虚御风,而不知其所止;飘飘乎如遗世独立,羽化而登仙。
于是饮酒乐甚,扣舷而歌之。歌曰:“桂棹兮兰桨,击空明兮溯流光。渺渺兮予怀,望美人兮天一方。”客有吹洞箫者,倚歌而和之。其声呜呜然,如怨如慕,如泣如诉;余音袅袅,不绝如缕。舞幽壑之潜蛟,泣孤舟之嫠妇。
  苏子愀然,正襟危坐,而问客曰:“何为其然也?”客曰:“‘月明星稀,乌鹊南飞。’此非曹孟德之诗乎?西望夏口,东望武昌,山川相缪,郁乎苍苍,此非孟德之困于周郎者乎?方其破荆州,下江陵,顺流而东也,舳舻千里,旌旗蔽空,酾酒临江,横槊赋诗,固一世之雄也,而今安在哉?况吾与子渔樵于江渚之上,侣鱼虾而友麋鹿,驾一叶之扁舟,举匏樽以相属。寄蜉蝣于天地,渺沧海之一粟。哀吾生之须臾,羡长江之无穷。挟飞仙以遨游,抱明月而长终。知不可乎骤得,托遗响于悲风。”
  苏子曰:“客亦知夫水与月乎?逝者如斯,而未尝往也;盈虚者如彼,而卒莫消长也。盖将自其变者而观之,则天地曾不能以一瞬;自其不变者而观之,则物与我皆无尽也,而又何羡乎!且夫天地之间,物各有主,苟非吾之所有,虽一毫而莫取。惟江上之清风,与山间之明月,耳得之而为声,目遇之而成色,取之无禁,用之不竭。是造物者之无尽藏也,而吾与子之所共适。”
  客喜而笑,洗盏更酌。肴核既尽,杯盘狼籍。相与枕藉乎舟中,不知东方之既白。


题目传送门(内部题30)


输入格式

第一行包含三个非负整数$N,M$和$K,N$,$M$意义如上,$K$为小数点后保留位数。


输出格式

包含一个小数点后$K$位的实数,注意四舍五入。


样例

样例输入:

3 3 3

样例输出:

0.667


数据范围与提示

样例解释:

$N=3$的排列有$6$个:$123,132,213,231,312,321$;他们的波动强度分别为$2,3,3,3,3,2$。
所以,赤壁之意不小于$3$的概率是$\frac{4}{6}$,即$0.667$。
你也可以通过下面的代码来验证这个概率:

int a[3]={0,1,2}, s=0, n=3;
for (int i=0; i<1000000; i++){
random_shuffle(a,a+n);
int t=0;
for (int j=0; j<n-1; j++) t += abs(a[j+1]-a[j]);
if (t>=3) s++;
}
printf("%.3f\n",s/1000000.0);

数据范围:


题解

这也许是我见过最恶心的题了……

你看着数据范围,保留$30$位小数,__float128,自闭了。

言归正转,开始说题解。

我们从大到小依次插入这些数。

还是考虑$DP$,设$dp[i][j][k][l]$表示插到了第$i$个数,当前对答案的贡献为$j$,加入数字形成了$k$段数,边界上已经有了$l$个数的方案数。

什么玩意儿这是?

我来解释一下,$i,j$就不做过多解释了,都懂。

先来解释$k$,如下图中,蓝色区域为整个序列,橙色区域为已经填了数的区域,那么下面就有$4$段数,$k$为$4$:

在来解释一下$l$,分为以下四种情况:

边界处没有数,$l=0$:

左边界有数,$l=1$:

右边界有数,$l=1$,但是在统计方案数的时候可以与上面的情况归在一起,毕竟序列可以从左往右,也可以从右往左:

两边都有数,$l=2$:

现在解释完了$DP$的意义,那么先不要考虑转移,先来考虑在插入$i$的时候的贡献。

为简化问题,也为了你能更好的理解下面式子的意义,我们在插入一个数的时候,可以先将它的贡献加上,然后再在它旁边插入一个数的时候减去。

那么,分为一下三种情况:

  $\alpha.$若数字$i$加入时新加入一个段,那数字$i$的贡献是$-2\times i$,因为如果新开了一段,这个数字两边的数肯定要比这个数字大。
  $\beta.$若数字$i$加入时段数没有改变,则$i$对波动程度没有影响,因为一边数字已加,另一边数字没有加,$i$的贡献$=-i+i$。
  $\gamma.$若数字$i$加入时将两段数合并,那数字$i$个贡献数$2\times i$,因为$i$两边的数已加,且比$i$小。

现在可以考虑转移了,列出$13$个状态转移方程……

$dp[i][j-i\times 2][k+1][0]+=dp[i-1][j][k][0]\times (k+1)$

  在中间插入一段新的,且没有段在边界:  

$dp[i][j][k][0]+=dp[i-1][j][k][0]\times k\times 2$

  挨着插,且没有段在边界:  

$dp[i][j+i\times 2][k-1][0]+=dp[i-1][j][k][0]\times (k-1)$

  合并两段,且没有段在边界:

$dp[i][j-i][k+1][1]+=dp[i-1][j][k][0]\times 2$

  在边界上增加一段,且另一个边界没有:

$dp[i][j+i][k][1]+=dp[i-1][j][k][0]\times 2$

  连接一段和边界:

$dp[i][j-i\times 2][k+1][1]+=dp[i-1][j][k][1]\times k$

  有一段在边界,再添加一个不在边界上的新段:

$dp[i][j][k][1]+=dp[i-1][j][k][1]\times (k\times 2-1)$

  有一段在边界,挨着一段添加一个:

$dp[i][j+i\times 2][k-1][1]+=dp[i-1][j][k][1]\times (k-1)$

  有一段在边界,添加的时候合并了两段:

$dp[i][j-i][k+1][2]+=dp[i-1][j][k][1]$

  有一段在边界上,再添加一段新的在另一个边界上:

$dp[i][j+i][k][2]+=dp[i-1][j][k][1]$

  有一个在边界上,添加一个让一段与另一个边界相连:

$dp[i][j-i\times 2][k+1][2]+=dp[i-1][j][k][2]\times (k-1)$

  有两个在边界上,添加一个新段:

$dp[i][j][k][2]+=dp[i-1][j][k][2]\times (k\times 2-2)$

  有两个在边界上,挨着一段添加一个:

$dp[i][j+i\times 2][k-1][2]+=dp[i-1][j][k][2]\times (k-1)$

  有两个在边界上,添加一个合并两段:

状态转移以及解释就这么多了

注意需要打数据点分治,最后一个点再用__float128,否则会超时。

至于$m$非常大,其实并没有什么关系。因为$n$最大是$100$,那么$m$太大了也没有用。自己定义一个最大值就好。不用写高精度。

时间复杂度:$\Theta(24000\times n^2)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
int n,m,K;
int maxn[101];
bool pos;
double dp13[2][17000][101][3],ans13;
__float128 dp02[2][17000][101][3],ans02;
int sta[31];
int floor(__float128 x){for(int i=9;i>=0;--i)if(x>=i)return i;}
void print__float128(__float128 x,int ws)
{
for(int i=1;i<=ws;++i)x*=10,sta[i]=floor(x),x-=floor(x);
x*=10;if(floor(x)>=5)sta[ws]++;
for(int i=ws;i;--i)if(sta[i]==10)sta[i]=0,sta[i-1]++;
if(!ws){printf("%d",sta[0]);return;}
printf("%d.",sta[0]);
for(int i=1;i<=ws;++i)printf("%d",sta[i]);
}
int main()
{
scanf("%d%d%d",&n,&m,&K);
if(K<=8)
{
dp13[0][7998][1][0]=1;
dp13[0][7999][1][1]=2;
dp13[0][8000][1][2]=1;
for(int i=1;i<=n;i++)maxn[i]=min(i,n-i+1);
for(int i=2;i<=n;i++)
{
int size=min(8000,i*(i+1));
pos^=1;
for(int k=1;k<=maxn[i];k++)
for(int j=-size+8000;j<=size+8000;j++)
dp13[pos][j][k][0]=dp13[pos][j][k][1]=dp13[pos][j][k][2]=0;
for(int k=1;k<=maxn[i-1];k++)
for(int j=-size+8000;j<=size+8000;j++)
{
dp13[pos][j-i*2][k+1][0]+=dp13[!pos][j][k][0]*(k+1);
dp13[pos][j][k][0]+=dp13[!pos][j][k][0]*k*2;
dp13[pos][j+i*2][k-1][0]+=dp13[!pos][j][k][0]*(k-1);
dp13[pos][j-i][k+1][1]+=dp13[!pos][j][k][0]*2;
dp13[pos][j+i][k][1]+=dp13[!pos][j][k][0]*2;
dp13[pos][j-i*2][k+1][1]+=dp13[!pos][j][k][1]*k;
dp13[pos][j][k][1]+=dp13[!pos][j][k][1]*(k*2-1);
dp13[pos][j+i*2][k-1][1]+=dp13[!pos][j][k][1]*(k-1);
dp13[pos][j-i][k+1][2]+=dp13[!pos][j][k][1];
dp13[pos][j+i][k][2]+=dp13[!pos][j][k][1];
dp13[pos][j-i*2][k+1][2]+=dp13[!pos][j][k][2]*(k-1);
dp13[pos][j][k][2]+=dp13[!pos][j][k][2]*(k*2-2);
dp13[pos][j+i*2][k-1][2]+=dp13[!pos][j][k][2]*(k-1);
}
}
for(int i=m+8000;i<=16999;i++)
ans13+=dp13[pos][i][1][2];
for(int i=1;i<=n;i++)ans13/=i;
switch(K)
{
case 0:printf("%lf",ans13);break;
case 1:printf("%.1lf",ans13);break;
case 2:printf("%.2lf",ans13);break;
case 3:printf("%.3lf",ans13);break;
case 4:printf("%.4lf",ans13);break;
case 5:printf("%.5lf",ans13);break;
case 6:printf("%.6lf",ans13);break;
case 7:printf("%.7lf",ans13);break;
case 8:printf("%.8lf",ans13);break;
}
}
else
{
dp02[0][7998][1][0]=1;
dp02[0][7999][1][1]=2;
dp02[0][8000][1][2]=1;
for(int i=1;i<=n;i++)maxn[i]=min(i,n-i+1);
for(int i=2;i<=n;i++)
{
int size=min(8000,i*(i+1));
pos^=1;
for(int k=1;k<=maxn[i];k++)
for(int j=-size+8000;j<=size+8000;j++)
dp02[pos][j][k][0]=dp02[pos][j][k][1]=dp02[pos][j][k][2]=0;
for(int k=1;k<=maxn[i-1];k++)
for(int j=-size+8000;j<=size+8000;j++)
{
dp02[pos][j-i*2][k+1][0]+=dp02[!pos][j][k][0]*(k+1);
dp02[pos][j][k][0]+=dp02[!pos][j][k][0]*k*2;
dp02[pos][j+i*2][k-1][0]+=dp02[!pos][j][k][0]*(k-1);
dp02[pos][j-i][k+1][1]+=dp02[!pos][j][k][0]*2;
dp02[pos][j+i][k][1]+=dp02[!pos][j][k][0]*2;
dp02[pos][j-i*2][k+1][1]+=dp02[!pos][j][k][1]*k;
dp02[pos][j][k][1]+=dp02[!pos][j][k][1]*(k*2-1);
dp02[pos][j+i*2][k-1][1]+=dp02[!pos][j][k][1]*(k-1);
dp02[pos][j-i][k+1][2]+=dp02[!pos][j][k][1];
dp02[pos][j+i][k][2]+=dp02[!pos][j][k][1];
dp02[pos][j-i*2][k+1][2]+=dp02[!pos][j][k][2]*(k-1);
dp02[pos][j][k][2]+=dp02[!pos][j][k][2]*(k*2-2);
dp02[pos][j+i*2][k-1][2]+=dp02[!pos][j][k][2]*(k-1);
}
}
for(int i=m+8000;i<=16999;i++)
ans02+=dp02[pos][i][1][2];
for(int i=1;i<=n;i++)ans02/=i;
print__float128(ans02,K);
}
return 0;
}

rp++

[CSP-S模拟测试]:赤壁情(DP)的更多相关文章

  1. [CSP-S模拟测试]:B(DP+数学)

    题目传送门(内部题45) 输入格式 第一行$3$个整数$n,m,P$.第二行$m$个整数,表示$m$次询问. 输出格式 一行$m$个整数表示答案. 样例 样例输入1: 2 4 40 1 2 3 样例输 ...

  2. [CSP-S模拟测试]:蛇(DP+构造+哈希)

    题目传送门(内部题140) 输入格式 前两行有两个长度相同的字符串,描述林先森花园上的字母. 第三行一个字符串$S$. 输出格式 输出一行一个整数,表示有多少种可能的蛇,对$10^9+7$取模. 样例 ...

  3. [CSP-S模拟测试]:最小值(DP+乱搞)

    题目背景 $Maxtir$更喜欢序列的最小值. 题目传送门(内部题128) 输入格式 第一行输入一个正整数$n$和四个整数$A,B,C,D$. 第二行输入$n$个整数,第$i$个数表示$a_i$. 输 ...

  4. [CSP-S模拟测试]:花(DP)

    题目传送门(内部题111) 输入格式 一个整数$T$,表示测试数据组数. 每组测试数据占一行,两个整数,分别表示$L$和$S$. 输出格式 对每组数据,输出一个整数表示答案. 样例 样例输入1: 13 ...

  5. [CSP-S模拟测试]:计数(DP+记忆化搜索)

    题目描述 既然是萌萌哒$visit\text{_}world$的比赛,那必然会有一道计数题啦!考虑一个$N$个节点的二叉树,它的节点被标上了$1\sim N$的编号.并且,编号为$i$的节点在二叉树的 ...

  6. [CSP-S模拟测试]:matrix(DP)

    题目描述 求出满足以下条件的$n\times m$的$01$矩阵个数:(1)第$i$行第$1~l_i$列恰好有$1$个$1$.(2)第$i$行第$r_i~m$列恰好有$1$个$1$.(3)每列至多有$ ...

  7. [CSP-S模拟测试]:题(DP+数学)

    题目描述 出个题就好了.这就是出题人没有写题目背景的原因.你在平面直角坐标系上.你一开始位于$(0,0)$.每次可以在上/下/左/右四个方向中选一个走一步.即:从$(x,y)$走到$(x,y+1),( ...

  8. [CSP-S模拟测试]:题(DP)

    题目描述 由于出题人赶时间所以没办法编故事来作为背景.一开始有$n$个苹果,$m$个人依次来吃苹果,第$i$个人会尝试吃$u_i$或$v_i$号苹果,具体来说分三种情况.$\bullet 1.$两个苹 ...

  9. [CSP-S模拟测试]:y(DP+bitset)

    题目背景 $\frac{1}{4}$遇到了一道水题,叕完全不会做,于是去请教小$D$.小$D$懒得理$\frac{1}{4}$,直接就离开了.于是,$\frac{1}{4}$只好来问你,这道题是这样的 ...

随机推荐

  1. 异常检测算法的Octave仿真

    在基于高斯分布的异常检测算法一文中,详细给出了异常检测算法的原理及其公式,本文为该算法的Octave仿真.实例为,根据训练样例(一组网络服务器)的吞吐量(Throughput)和延迟时间(Latenc ...

  2. MySQL-第九篇分组和组函数

    1.组函数 组函数:即多行函数,组函数将一组记录作为整体计算,每组记录返回一个结果,而不是每条记录返回一个结果. 2.常用的组函数有: 1>avg([distinct|all]expr):计算多 ...

  3. 数据溢出-varchar类型

    数据溢出一.varchar(65535)1.在charset=latin1,因为有额外的开销,实际只能存65532 CREATE table demo( a ) )charset=latin1 eng ...

  4. P2747 [USACO5.4]周游加拿大Canada Tour

    题目描述 你赢得了一场航空公司举办的比赛,奖品是一张加拿大环游机票.旅行在这家航空公司开放的最西边的城市开始,然后一直自西向东旅行,直到你到达最东边的城市,再由东向西返回,直到你回到开始的城市.除了旅 ...

  5. 2.etcd集群的安装(cfssl版)

    etcd的安装注意两点 1.systemd的配置文件   2. 证书 1. 解决 systemd的问题,想安装指定版本的etcd可以通过 yum方式安装 etcd 可以获得 systemc 和 etc ...

  6. #python# error:UnicodeEncodeError: 'latin-1' codec can't encode character '\u2026' in position 30: ordinal not in range(256)

    headers={ 'Referer':'https://www.lagou.com/jobs/lis-rds=&fromSearch=true&suginput=', 'User-A ...

  7. [fw]Linux系统使用time计算命令执行的时间

    Linux系统使用time计算命令执行的时间 当测试一个程序或比较不同算法时,执行时间是非常重要的,一个好的算法应该是用时最短的.所有类UNIX系统都包含time命令,使用这个命令可以统计时间消耗.例 ...

  8. 莫比乌斯反演/线性筛/积性函数/杜教筛/min25筛 学习笔记

    最近重新系统地学了下这几个知识点,以前没发现他们的联系,这次总结一下. 莫比乌斯反演入门:https://blog.csdn.net/litble/article/details/72804050 线 ...

  9. mac文本操作小技巧——2019年10月17日

    声明:看的别人博主写的,自己整理的,非原创,只是自用. mac文本操作技巧 官方指导文档:https://support.apple.com/zh-cn/HT201236 1.光标移动 1.1 行首. ...

  10. 日常Git使用——2019年12月11日16:19:03

    1.git介绍 1.1 什么是git? 什么是Git? 比如一个项目,两个人同时参与开发,那么就把这个项目放在一个公共的地方,需要的时候都可以去获取,有什么改动,都可以进行提交. 为了做到这一点,就需 ...