GDOI2016 day1题解
2016-05-10 17:44
176 查看
由于现在从机房转移到了电阅,时间不是很够啊……只能把三天的题解分开写了……(写个鬼的题解啊……政治测验还55呢……-.-)
T1:
题意:有两个数p1,p2,设n1=[n0-k*p1],n2=[n0-k*p2]-n1,求(p1-p0)*n1+(p2-p0)*n2的最大值
1<=n0<=100w,n1>=0,n2>=0,p1>=0,.p2>=0,k>=0
显然要求的是一个二元函数……要求最值还是很复杂的……我们考虑枚举一个元素,因为0<=n1<=n0<=100w,所以可以枚举n1,p1当然是越大越好,所以n1=n0-k*p1
当n2相同的时候,p2也是越大越好
所以可以把讨厌的取整符号消掉
然后当n1固定的时候,所求的式子是关于n2的二次函数
首先,比较厉害的人想到,二次函数是单峰函数,可以三分
然而由于我太水了,只能想到课本上二次函数求最值的公式
于是直接套公式就可以了
注意n2是整数,所以要取离对称轴最近的整点,我直接四舍五入了(好像这道题如果卡精度我就炸了)
T2:
题意:有两个字符串s,t,给出k个区间,我们定义一个操作,对于第i个区间li,ri,我们可以把s[li]-s[ri]中的字符任意排列
你可以执行任意次操作
问s和t的最长公共子串
len(s)<=1000,len(t)<=1000(好像是2000?),k<=10w
首先想到区间显然可以合并
那么我们把单个的也当成区间,比如j当成区间[j,j],再把区间排序,那么区间个数可以降到至多len(s)个,而且因为区间肯定没有交集(有交集的都被合并掉了),所以对于每个区间只需要执行一次操作
因为区间能任意排列,所以我们可以想到计数,只要对字符数计数求出前缀和,那么区间有哪些字符是可以在O(26)的时间内求出来的
然后就可以用类似dp的方法搞了
先求出f[i][j]表示第i个区间与t中以第j个字符开始的后缀的最长公共前缀,显然如果对s和t都计数了的话可以O(26)求f[i][j]
然后我们设l[i][j]表示最多可以向左延伸多少个字符,r[i][j]表示最多可以向右延伸多少个字符
我们可以分类讨论一下,对于一个区间,如果它的f值等于区间长度,那么填满这个区间之后还可以延伸,所以l[i][j]=l[i-1][j-len[i-1]]+len[i-1],r[i][j]=r[i+1][j+len[i]]+len[i]
否则最多只能让这个区间填上f[i-1][j-len[i-1]]个字符
然后有了l[i][j],r[i][j],f[i][j]就可以直接算出答案了
注意有坑:
如果j前面并不能拼上一个区间然而有一些字符是匹配的,很有可能答案就是i这个区间向两边延伸的区间长度,然而j-len[i-1]是负数……搞不了……
我们可以把t前面加上len(s)个没有出现过也不会被计数的字符,这样就可以搞啦
同理如果j后面不能拼上一个区间然而有一些字符是匹配的,那么用同样的方法把t后面也加上len(s)个没有出现过也不会被计数的字符
正解貌似不是这样?求正解……我觉得这样可以搞,求喷
T3:
我们可以设f[i][j][k][l]为有i个数,j个位置,k个数已经确定在密码里面,l个数已经确定在密码里面且不在第一个位置
那么决策有两种
选择一个已经确定在密码里面的数填入位置1,选择一个还没确定在密码里面的数填入位置1
这个时候就要分类讨论了
首先,如果第一个位置是已经确定在密码里面的数,出现这种情况的概率是(k-l)/(i-l)
那么如果猜已经确定在密码里面的数
有1/(k-l)的概率刚好选中
有k-l-1/(k-l)的概率没选中
如果猜还没确定在密码里面的数
有i-k个数,j-k个给这些数的位置
所以有(j-k)/(i-k)的概率在密码里面
有(i-j)/(i-k)的概率不在密码里面
如果第一个位置是还没确定在密码里面的数,出现这种情况的概率是(i-k)/(i-l)
那么如果猜已经确定在密码里面的数一定没选中
如果猜还没确定在密码里面的数
有i-k个数,j-k个给这些数的位置,而且其中一个位置是1
所以有1/(i-k)的概率刚好选中
有(j-k-1)/(i-k)的概率在密码里面
有(i-j)/(i-k)的概率不在密码里面
然后就可以转移了
f[i][j][k][l]=min(1/(i-l)*f[i-1][j-1][k-1][0]+(i-l-1)/(i-l)*f[i][j][k][l+1],1/(i-l)*f[i-1][j-1][k][0]+((j-k)(k-l)/(i-k)(i-l)+(j-k-1)/(i-k))*f[i][j][k+1][l+1]+((i-j)(k-l)/(i-k)(i-l)+(i-j)/(i-l))*f[i-1][j][k][l])
然后题目要求取模,取模显然不能取min,所以要开两个数组,f记录答案取模后的答案,另一个是double类型记录真正的答案,然后直接做就可以啦
T4:
裸题……只不过……?GDOI的防ak题……代码量……
单点修改直接在线段树上改
查询的话一个末项为1的等差数列就是左半边乘上一个末项为1的等差数列加区间和*x加右半边乘上一个末项为1的等差数列
区间和和区间乘上一个末项为1的等差数列都可以维护,注意是在树上有方向问题所以有可能乘上一个首项为1的等差数列
树上?树剖不就好了
查询历史值?可持久化
很裸很难打……没什么好说的……
T1:
题意:有两个数p1,p2,设n1=[n0-k*p1],n2=[n0-k*p2]-n1,求(p1-p0)*n1+(p2-p0)*n2的最大值
1<=n0<=100w,n1>=0,n2>=0,p1>=0,.p2>=0,k>=0
显然要求的是一个二元函数……要求最值还是很复杂的……我们考虑枚举一个元素,因为0<=n1<=n0<=100w,所以可以枚举n1,p1当然是越大越好,所以n1=n0-k*p1
当n2相同的时候,p2也是越大越好
所以可以把讨厌的取整符号消掉
然后当n1固定的时候,所求的式子是关于n2的二次函数
首先,比较厉害的人想到,二次函数是单峰函数,可以三分
然而由于我太水了,只能想到课本上二次函数求最值的公式
于是直接套公式就可以了
注意n2是整数,所以要取离对称轴最近的整点,我直接四舍五入了(好像这道题如果卡精度我就炸了)
T2:
题意:有两个字符串s,t,给出k个区间,我们定义一个操作,对于第i个区间li,ri,我们可以把s[li]-s[ri]中的字符任意排列
你可以执行任意次操作
问s和t的最长公共子串
len(s)<=1000,len(t)<=1000(好像是2000?),k<=10w
首先想到区间显然可以合并
那么我们把单个的也当成区间,比如j当成区间[j,j],再把区间排序,那么区间个数可以降到至多len(s)个,而且因为区间肯定没有交集(有交集的都被合并掉了),所以对于每个区间只需要执行一次操作
因为区间能任意排列,所以我们可以想到计数,只要对字符数计数求出前缀和,那么区间有哪些字符是可以在O(26)的时间内求出来的
然后就可以用类似dp的方法搞了
先求出f[i][j]表示第i个区间与t中以第j个字符开始的后缀的最长公共前缀,显然如果对s和t都计数了的话可以O(26)求f[i][j]
然后我们设l[i][j]表示最多可以向左延伸多少个字符,r[i][j]表示最多可以向右延伸多少个字符
我们可以分类讨论一下,对于一个区间,如果它的f值等于区间长度,那么填满这个区间之后还可以延伸,所以l[i][j]=l[i-1][j-len[i-1]]+len[i-1],r[i][j]=r[i+1][j+len[i]]+len[i]
否则最多只能让这个区间填上f[i-1][j-len[i-1]]个字符
然后有了l[i][j],r[i][j],f[i][j]就可以直接算出答案了
注意有坑:
如果j前面并不能拼上一个区间然而有一些字符是匹配的,很有可能答案就是i这个区间向两边延伸的区间长度,然而j-len[i-1]是负数……搞不了……
我们可以把t前面加上len(s)个没有出现过也不会被计数的字符,这样就可以搞啦
同理如果j后面不能拼上一个区间然而有一些字符是匹配的,那么用同样的方法把t后面也加上len(s)个没有出现过也不会被计数的字符
正解貌似不是这样?求正解……我觉得这样可以搞,求喷
T3:
我们可以设f[i][j][k][l]为有i个数,j个位置,k个数已经确定在密码里面,l个数已经确定在密码里面且不在第一个位置
那么决策有两种
选择一个已经确定在密码里面的数填入位置1,选择一个还没确定在密码里面的数填入位置1
这个时候就要分类讨论了
首先,如果第一个位置是已经确定在密码里面的数,出现这种情况的概率是(k-l)/(i-l)
那么如果猜已经确定在密码里面的数
有1/(k-l)的概率刚好选中
有k-l-1/(k-l)的概率没选中
如果猜还没确定在密码里面的数
有i-k个数,j-k个给这些数的位置
所以有(j-k)/(i-k)的概率在密码里面
有(i-j)/(i-k)的概率不在密码里面
如果第一个位置是还没确定在密码里面的数,出现这种情况的概率是(i-k)/(i-l)
那么如果猜已经确定在密码里面的数一定没选中
如果猜还没确定在密码里面的数
有i-k个数,j-k个给这些数的位置,而且其中一个位置是1
所以有1/(i-k)的概率刚好选中
有(j-k-1)/(i-k)的概率在密码里面
有(i-j)/(i-k)的概率不在密码里面
然后就可以转移了
f[i][j][k][l]=min(1/(i-l)*f[i-1][j-1][k-1][0]+(i-l-1)/(i-l)*f[i][j][k][l+1],1/(i-l)*f[i-1][j-1][k][0]+((j-k)(k-l)/(i-k)(i-l)+(j-k-1)/(i-k))*f[i][j][k+1][l+1]+((i-j)(k-l)/(i-k)(i-l)+(i-j)/(i-l))*f[i-1][j][k][l])
然后题目要求取模,取模显然不能取min,所以要开两个数组,f记录答案取模后的答案,另一个是double类型记录真正的答案,然后直接做就可以啦
T4:
裸题……只不过……?GDOI的防ak题……代码量……
单点修改直接在线段树上改
查询的话一个末项为1的等差数列就是左半边乘上一个末项为1的等差数列加区间和*x加右半边乘上一个末项为1的等差数列
区间和和区间乘上一个末项为1的等差数列都可以维护,注意是在树上有方向问题所以有可能乘上一个首项为1的等差数列
树上?树剖不就好了
查询历史值?可持久化
很裸很难打……没什么好说的……
相关文章推荐
- [MZ test.16]P1 评测
- 请实现一个函数,把字符串中的每个空格换成20%
- android Layout技巧汇总
- 软件结构图补充
- 8. Android框架和工具之 NineOldAndroids(动画框架)
- Android WebView 不支持 H5 input type="file" 解决方法
- Android_LoaderManager获取联系人
- 基于springjdbc封装的javaee轻量级开发平台jmapper(一)
- 怎样写一个增广矩阵到txt文件中
- c++第五次实验——数组分离
- Windows 10新增的6个快捷键:
- 实验一 框架的选择及其原因
- 计算器第五次作业
- CSS
- poj 2831(次小生成树)
- java.lang.NoClassDefFoundError: Could not initialize class org.hibernate.validator.internal.engine.m
- 不错的第三方
- mac可以上QQ,打不开网页,上不了网
- 关于TortoiseSVN的全局忽略列表
- 蓝牙L2CAP剖析(二)