您的位置:首页 > 其它

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的等差数列

树上?树剖不就好了

查询历史值?可持久化

很裸很难打……没什么好说的……
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: