每一年都奔走在自己热爱里

没有人是一座孤岛,总有谁爱着你

Educational Codeforces Round 144 (Rated for Div. 2)(A,B,C,D)

Educational Codeforces Round 144 (Rated for Div. 2)(A,B,C,D)

本来这场我是要vp的,但是后来第一个题wa了一次,心态崩了,就没有看了,后面才补的

A

A

这个就是求一个串是不是另外一个串的子串,我都知道了这个另外一个串是什么了,就是我是自己写的判断两个字符串是否是为子串的关系写错了(还是太弱了),其实我们可以看到k的大小是不大的,所以我们可以根据我所得到的的规律构造一个串(长度比k大),然后利用find来判断

我觉得我在做这个题的时候没有看到那个k的范围,然后就一股脑的去写,ε=(´ο`*)))

#include <iostream>
#include <string>
using namespace std;
const int manx=2e5+10;
int t,n;
string ss="FBFFBFFB";
void solve()
{
    string s;
    cin>>n;
    cin>>s;
    if (ss.find(s)!=-1)
    {
        cout<<"YES\n";
    }
    else cout<<"NO\n";
    return ;
}
int main ()
{
    cin>>t;
    ss=ss+ss+ss;
    while (t--)
    {
        solve();
    }
    system ("pause");
    return 0;
}

B

B

这个是我后面自己写的

题目大意就是我们可以用一个既有又有字母的字符串,我们可以把变成任意的字符(长度不定),然后给出我们两个字符串,找到一个上面所述的形式的字符,这个字符串可以得到这两种字符,但是还要满足字母的数量不可以大于的数量

我们可以知道,如果对于两个字符串都存在的字符,那么那么这一个字符就可以直接显示出来,而不需要通过变成,所以对于那些两个字符串都存在的字符,我们就是以字母的形式

然后我们对于那些不同的,我们直接用变成

然后我们还知道aa这样的字符串,一定是大于字母的数量的

所以我们只有两端的字符是一样的,那么我们后面都由 变成,符号条件

那么对于那些两端不同的,只有中间存在两个连续的字符在两个字符串里面是一样的,那么就会变成ab,符号条件,如果不满足,那么就只有a,不满足条件

#include <iostream>
#include <string>
using namespace std;
const int maxn=2e5+10;
#define yes cout<<"YES\n"
#define no cout<<"NO\n";
int t;
string s,ss;
void solve()
{
    cin>>s>>ss;
    if (s[0]==ss[0])
    {
        yes;
        cout<<s[0]<<"*\n";
        return ;
    }
    int n=s.size(),nn=ss.size();
    if (s[n-1]==ss[nn-1])
    {
        yes;
        cout<<"*"<<s[n-1]<<'\n';
        return ;
    }
    for (int i=0;i+1<n;i++)
    {
        for (int j=0;j+1<nn;j++)
        {
            if (s[i]==ss[j]&&s[i+1]==ss[j+1])
            {
                yes;
                cout<<"*"<<s[i]<<s[i+1]<<"*\n";
                return ;
            }
        }
    }
    no;
    return ;
}
int main ()
{
    cin>>t;
    while (t--)
    {
        solve();
    }
    system ("pause");
    return 0;
}

C

C

题目大意就是给你一对lr,我们需要在这一段里面找任意个数,使得我所选择的数是两两可整除的,问我所选择的数的数量最大是多少,这个数量的数有多少种选择

首先我们需要知道这个最大的数量是多大

要满足数量最多,那么这个最小的数一定是l,要满足两两可整除,那么后面的我们可以依次乘2,那么最大数量len,第len大的数是$ l\times 2^{len-1},rlen=log2(r/l)$,对于所有的都是2,然后我们还可以把这个2替换成3,但是不可以是4,一定是不满足的

对于最大的数是最小的数的2len1(mul)倍,只要这个最大的在r的范围内的均可,所以对于这一种倍数满足条件的有多少个,我们可以求出最后一个满足这个条件( r/mul)的,那么这个数到l的范围都是满足条件的

但是注意对于把任意个2变成3,有不同的组合方式

#include <iostream>
#include <cmath>
using namespace std;
#define int long long 
const int mod=998244353;
int n,t,l,r;
int c[40][40];
void init()
{
    for (int i=0;i<=30;i++)
    {
        for (int j=0;j<=i;j++)
        {
            if (!j)
            {
                c[i][j]=1;
            }
            else 
            {
                c[i][j]=c[i-1][j-1]+c[i-1][j];
            }
        }
    }
    return ;
}
void solve()
{
    cin>>l>>r;
    int len=__lg(r/l);
    int mul=1<<len;
    int ans=0;
    for (int i=0;i<=len;i++)
    {
        if (l*mul>r) break;
        ans=(ans+c[len][i]*(r/mul-l+1)%mod)%mod;
        mul=mul*3/2;
    }
    cout<<len+1<<" "<<ans<<'\n';
    return ;
}
signed main ()
{
    cin>>t;
    init();
    while (t--)
    {
        solve();
    }
    system ("pause");
    return 0;
}

D

D

这个大意是给你一个n个数,我们需要选择k个数,把这k个数加x,其余的减x,问最大子段和

这个我们可以参考普通的最大字段和

for (int i=1;i<=n;i++)
{
    dp[i]=max(dp[i-1]+a[i],a[i]);//以i为结尾的最大子段和
}

最大子段和

然后我们这个题还需要选择k个加x,其余减x的变化

所以我们还需要多一维来表达这个位置是加还是减,还需要记录此时已经有了多少个加了

那么对于dp[i][j][x][y]代表此时已经遍历的i的长度,已经有了j个加法操作了,x0,1表示,代表i位置的数是加法还是减法,y0,1表示,代表i位置的数放进子段里面还是不放

然后我们就可以很容易的得出状态转移方程

 if (i>j)//最多只能有i-1个,他前面只有i-1个位置(不包括i),第i个进行减法操作
 {
     dp[i][j][0][0]=max(dp[i-1][j][0][0],max(dp[i-1][j][0][1],max(dp[i-1][j][1][0],max(dp[i-1][j][1][1],0ll))));
     dp[i][j][0][1]=max(dp[i-1][j][0][1]+t0,max(dp[i-1][j][1][1]+t0,t0));
 }
if (j)//加法操作,这一项的j可以等于i,可以前面到i都是加法
{
    dp[i][j][1][0]=max(dp[i-1][j-1][0][0],max(dp[i-1][j-1][0][1],max(dp[i-1][j-1][1][0],max(dp[i-1][j-1][1][1],0ll))));
    dp[i][j][1][1]=max(dp[i-1][j-1][0][1]+t1,max(dp[i-1][j-1][1][1]+t1,t1));
}

具体代码如下

#include <iostream>
using namespace std;
const int maxn=2e5+10;
#define int long long 
int dp[maxn][30][2][2];
int a[maxn];
int n,k,x;
void solve()
{
    cin>>n>>k>>x;
    for (int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    for (int i=0;i<2;i++)
    {
        for (int j=0;j<2;j++)
        {
            dp[0][0][i][j]=0;
        }
    }
    for (int i=1;i<=n;i++)
    {
        for (int j=0;j<=min(i,k);j++)
        {
            int t1=a[i]+x;
            int t0=a[i]-x;
            if (i>j)//最多只能有i-1个,他前面只有i-1个位置(不包括i),第i个进行减法操作
            {
                dp[i][j][0][0]=max(dp[i-1][j][0][0],max(dp[i-1][j][0][1],max(dp[i-1][j][1][0],max(dp[i-1][j][1][1],0ll))));
                dp[i][j][0][1]=max(dp[i-1][j][0][1]+t0,max(dp[i-1][j][1][1]+t0,t0));
            }
            if (j)//加法操作,这一项的j可以等于i,可以前面到i都是加法
            {
                dp[i][j][1][0]=max(dp[i-1][j-1][0][0],max(dp[i-1][j-1][0][1],max(dp[i-1][j-1][1][0],max(dp[i-1][j-1][1][1],0ll))));
                dp[i][j][1][1]=max(dp[i-1][j-1][0][1]+t1,max(dp[i-1][j-1][1][1]+t1,t1));
            }
        }
    }
    int ans=0;
    for (int i=0;i<2;i++)
    {
        for (int j=0;j<2;j++)
        {
            ans=max(ans,dp[n][k][i][j]);
        }
    }
    cout<<ans<<'\n';
    return ;
}
signed main ()
{
    int t;
    cin>>t;
    while (t--)
    {
        solve();
    }
    system ("pause");
    return 0;
}
posted @   righting  阅读(64)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示