2021年OI集训队赛前模拟5题解

T1 保龄球大赛 思维

分1.把中立的人加到两个团体平均。2.加到人少的那一队这两种情况
当然也可以按照数据的范围去分类,即a大于b,a小于b,a等于b三种情况
十年OI一场空,不开long long见祖宗,这个题最后30分需要long long,需要特别注意。
其他题解请参考 luogu题解

T2 Base64编码 模拟

我们可以按照三个字符一分隔,中间过程即进制转换,ASCII码为256进制,Base64编码为64进制。
比如Web转换V2Vi的过程,其ASCII值分别为87,101,98。然后把当成256进制数,也就是x=87*256*256+102*256+98。得到x之后,要将其转换为64进制数,最低位可以%64得到,倒数第2位可以/64%64得到,倒数第3位可以/64/64%64得到,倒数第4位(最高位)可以/64/64/64得到,此数位下标,对应找到表里的值即可。然后将这个步骤转换为代码。
=号的话长度还剩1或2,特判即可。

T3 说无可说 DFS

这次就属于T4比T3难的情况,比赛一般情况下难度从前往后,但是也存在不是这样的情况,所以每个题都要阅读。
出题人的题解:
“对于30%的数据,字符串的总长度<=5000”
DP,枚举两个串A和B,设f[i][j]表示A中以第i位开始的字符串变成B中以第j为开始的字符串的最小次数
“对于40%的数据,字符串的总长度<=12000”
跟30%的一样,数组滚动就好了。
“对于60%的数据,字符串的总长度<=100000”
所以DP时很多状态都是无用的,因为如果两个串的长度差大于8那么对答案没有贡献
“对于另外20%的数据,1<=n<=70”
其实这档跟正解没有什么区别,好像也是可以过掉100分的,没有实测,但是分分钟跑的比正解快?!
由于只要求相似度小于等于8 的字符串对数,那么考虑递归的计算两个串的相似度,对于串A和B,假设当前我们已经匹配到x和y(x是A中的位置,y是B中的位置),那么首先跳过以这两个位置开头的LCS,然后三种操作继续递归下去,如果答案大于8就退出。
求LCS的时候就用hash+二分
“对于100%的数据,1<=n<=200,字符串的总长度<=1000000”
标程的方法是跳LCS的时候一个个跳...
loj上有很多ac代码可以参考

T4 散步 动态规划

和传纸条和方格取数类似,不过本题解决的是他两位置上之差的最大值,那么取完大之后求绝对值即可。
30分的代码(实际上可以得50分),你问我数组为甚么不直接开105,我只能说请你算下空间,不然这30都过不去。

#include<bits/stdc++.h>
using namespace std;
int a[51][51],sum[51][51][51][51],n,i,j,h,k,x,y,z;
int main()
{
    freopen("walk.in","r",stdin);
    freopen("walk.out","w",stdout);
    cin>>n;
    for(i=1;i<=n;i++)
    for(j=1;j<=n;j++)cin>>a[i][j];
    for(i=1;i<=n;i++)
    for(j=1;j<=n;j++)
    for(h=1;h<=n;h++)
    for(k=1;k<=n;k++)
    {
        int tmp1=max(sum[i-1][j][h-1][k],sum[i][j-1][h][k-1]);
        int tmp2=max(sum[i-1][j][h][k-1],sum[i][j-1][h-1][k]);
        sum[i][j][h][k]=max(tmp1,tmp2)+abs(a[i][j]-a[h][k]);
    }
    cout<<sum[n][n][n][n];
    return 0;
}

那么想要优化怎么办呢,需要考虑步数,从(1,1)走到(n,n)需要2n-1步,那我们直接枚举步数就可以了,考虑两个人同时走了k步,第一个人在 (i, k - i) 处,第二个人在 (j, k - j)处,分四种情况(1.同时向右 2.A右B下 3.A下B右 4.同时向下),也就是优化为O(n^3)的动态规划

posted @ 2021-10-17 20:09  暴力都不会的蒟蒻  阅读(92)  评论(0编辑  收藏  举报