苏州大学2020 ICPC集训队个人排位赛(1)

神秘代码:好像忘记专门设签到题了
B:https://codeforces.com/problemset/problem/510/B
C:https://codeforces.com/problemset/problem/1183/H
参考博客:https://blog.csdn.net/slark_/article/details/100713998
题意:给你一个字符串s,又给你一个数n,要你用s的子串填满一个数量为n的集合,对于每个子串,它和原来的串s相比,少了几个字符它就要付出多少代价(删去一个字符需要花费1个代价)。问你填满集合时代价最小是多少,如果填不满,输出-1。
思路:我们看数据范围,可以猜到是dp,那么具体的dp怎么写呢?我们想,对于每个位置,我们记录以这个位置上的字符为结尾的子串,也就是定义dp[i][len]为以第i个字母为子串最后一个字符,长度为len的子串有多少个。那么dp[i][len] += dp[前i-1个字符中最后的'a'-'z'][len-1]。
对于前i-1个字符中最后的'a'-'z',用一个数组来记录每个位置上其前面的'a'-'z'的位置。
然后我们开始按长度贪心,每个长度都是以'a'-'z'结尾的子串的数量的和。

//author CN.TTDragon
#include<bits/stdc++.h>
typedef long long ll;
const ll mod=1e9+7;
const ll maxn=1e5+7;
const double pi=acos(-1);
using namespace std;
char s[105];//原来的串
ll n,k;
int last[105][26]={0};//last 记录当前位置下,在其前面的最近的'a'-'z',没有的话就是-1
ll dp[105][105]={0};//dp[i][len]为以第i个字母为子串最后一个字符,长度为len的子串有多少个。
int main()
{
        ios::sync_with_stdio(false);
    memset(last,-1,sizeof(last));
    memset(dp,0,sizeof(dp));
    scanf("%lld %lld ",&n,&k);

    scanf("%s",s);
    //先来计算last
    last[0][s[0]-'a']=0;//第一个字符特殊处理掉,你要是从1计数,这里就可以省去了
    for(int i=1;i<n;i++)
    {
        for(int j=0;j<26;j++)
        {
            last[i][j]=last[i-1][j];//从前面接收来
        }
        last[i][s[i]-'a']=i;//修改当前位置上对应的字符
    }

    for(int i=0;i<n;i++)
    {
        dp[i][1]=1;//每个字符长度为一的子串就是自己 
    } 
    for (int i=2;i<n;i++)//i 是长度 
    {
        for (int j=1;j<n;j++)//j是坐标 
        {
            for(int k=0;k<26;k++)
            {
                if(last[j-1][k]!=-1)//前面有这个字符,没有就算了
                {
                    dp[j][i]+=dp[last[j-1][k]][i-1];
                }
            }
        } 
    }

    ll ans=0;
    k--;//原始串,不要代价 
    //接下来是个贪心的过程
    for(int i=n-1;i>=1;i--)//肯定是从n-1开始贪
    {
        ll cnt = 0;//有多少长度为i的子串 
        for(int j=0;j<26;j++)
        {
            if(last[n-1][j]!=-1)//如果这个字符存在,就把以它结尾的长度为i的子串数量加进来
                cnt+=dp[last[n-1][j]][i];    
        } 
        if(cnt>k)
        {
            ans+=(n-i)*k;
            k = 0;
            break;
        }
        else
        {
            ans+=(n-i)*cnt;
            k-=cnt;
        }

    } 

    if(k==1)//如果最后k还有,恰好有一个,那就是把空串""加进来
    {
        ans+=n;
        k--;
    }
    if(k==0)
        printf("%lld\n", ans);
    else//所有情况都出来了,真没串了
        printf("-1\n");
     return 0;
}

写在最后:
比赛的时候,看了眼C题,觉得能做,想到了组合数,结果写了半天(样例最后一个就是过不去),WA了。出来一看H题,直接自闭,太膨胀了。

全部评论

相关推荐

02-12 20:22
重庆大学 Java
字节暑期刚入职四天,因为是年前,所以很多正职都放假走了,也就没有给我分配mt,然后有一个老哥在我来的时候给我发了一个landing手册,然后还有关于部门业务的白皮书,还有一些业务代码。然后本人是java面的,进来第一次接触go语言 前面几天熟悉了一下go的语法和go的框架,可以读但是还不太会写,然后业务白皮书也看的很头疼,包括landing手册里要了解的很多东西说实话我看文档真的快看死了,一个嵌套一个,问题是我还完全不知道咋用这个我了解的东西,还有就是那个项目代码,那个老哥喊我去写写单测,熟悉一下go的语法,但也进行的很困难(这是我第一段实习,之前都是springboot那一套,真不太熟悉这个)想问问大家的建议,就是我从现在开始到在开年回来之前应该做些什么,我目前就一个想法 就是复现一个landing手册上的go框架小项目 就是相当于帮自己锻炼锻炼怎么写go 或者各位大佬有没有更好的锻炼go语法的建议还有就是大家都在说vibe coding,那我应该怎么锻炼自己使用ai的能力,感觉我除了给一些需求然后它给我生成代码,好像就没别的用法了,那些什么工作流、拆解、skill啥的都不知道从哪一个地方开始,包括我现在正在实习,不知道精力该怎么分配,去网上想找找关于agent开发的一些学习流程,说实话,众说纷纭,有的是从python开始打基础然后系统学那些rag prompt langchain mcp等等,有的是说直接找一个github上的ai项目然后反复问ai,我确实有点迷茫,恳求各位大佬能留下你们宝贵的建议,我一定认真反复深刻学习有一说一 我觉得字节饭挺好吃的!
双非后端失败第N人:1. go语言我建议你让ai带着你先把基本语法速通了,然后再去用go重新刷你以前刷过的leetcode,这样熟悉起来很快 2. 直接看你们组go项目,里面用***比较复杂,然后把每一个语法现象都喂给ai,一点点看
字节跳动公司福利 1371人发布
点赞 评论 收藏
分享
关于“实习生工资多少才算正常”,其实并没有一个放之四海而皆准的标准,但如果结合一线城市的生活成本、工作强度以及实习本身创造的价值来看,我个人认为6000 元左右应当是一个基本及格线,也就是每天 200 多元。如果能达到 300、400 元一天,甚至更高,那无疑是更理想的状态。首先,从现实成本看,房租、通勤、餐饮几乎都是刚性支出。低于这个水平的实习,往往意味着实习生需要用家庭或存款“倒贴”工作,这在长期来看并不合理。实习本质上是学习,但并不等于“廉价劳动力”,更不应该是经济压力的来源。其次,愿意给实习生更高薪资的公司,通常不会是差公司。这至少说明两点:一是公司资金相对充足,不是靠压缩人力成本勉强维持;二是公司认可实习生的价值,希望你真正参与业务、创造产出,而不是只做边角料工作。很多高薪实习往往伴随着更规范的培养体系、更高的信息密度和更真实的项目经验。当然,高工资并不等于一切,但它往往是一个重要信号。能给到 300、400 元一天甚至更多的公司,往往对效率、能力和长期发展更有追求,也更可能处在一个有前景的赛道中。总结来说,实习工资不仅是钱的问题,更是公司态度、实力和发展前景的体现。在条件允许的情况下,争取一份“付得起你时间”的实习,本身就是一种理性选择。
北国牛马:你是不是忘了你一周只能上五天班,月薪6000那你日薪就得300了,日薪200一个月也就4000,也就刚好覆盖生活成本了
实习生工资多少才算正常?
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务