10.3离线赛

预分:200 实分:175

写书
应得:100 实得:100

题意:计算1到n的数字出现个数

数据:对于100%,n∈[1,1e9];

小学奥数题,没有必要多想,一位数两位数三位数直接计算即可。

LR棋盘
应得:40 实得:35

题意:读入一个字符串,在串上有LR两种标记,L只能向左走,R只能向右走,每次只能走一个L或R,只能向没东西的格子走,问有多少种走法。最后对1e9+7取模

数据:对于40%,len∈[1,10],棋子数∈[1,5];
对于100%,len属于[1,20000],棋子数∈ [1,2000]

看到题后觉得要么是dp,要么是排列组合,因为要取模,不可能有暴力求解。
dp[i]定义为从1到i空有几种方法,但是这样就很难计算,因为LR可以移动到i的外面。
从另一个角度思考,因为LR放在一起时会变成一个独立的区间,那么可以单独处理最后相加,这样dp[i]就是1到第i个符号所有的方案数,只要再记录一下每个LR的区间即可

#include<bits/stdc++.h>
#define Mod 1000000007
#define M 200005
using namespace std;
char str[M];
int L[M],R[M],dp[M];
int main(){
    scanf("%s",str);
    int n=strlen(str);
    int cnt=0;
    for(int i=0;i<n;i++)
        if(str[i]=='L')cnt++,L[cnt]=0,R[cnt]=i;
        else if(str[i]=='R')cnt++,L[cnt]=i,R[cnt]=n-1;
    //记录LR的位置
    dp[0]=1;
    for(int i=0;i<n;i++)
        for(int j=cnt;j>=1;j--)
            if(L[j]<=i&&i<=R[j])//若满足i在这段区间内就加
                dp[j]+=dp[j-1],dp[j]%=Mod;
    printf("%d\n",dp[cnt]);
    return 0;
}

这个和之前有一道基因补全很像,那道是往一个序列里放数,这道题也可以这么想,只要保证他们的相对位置不变即可。

道路评价
应得:60 实得:40

题意:在一棵树上求任意两点见路径上最大值减最小值的差的和

数据:对于60%,n∈[1,5000];
对于100%,n属于[1,100000],边权∈[1,100000]

第一点,边权这么大,肯定要用long long才行
第二点,5000^2可以开一下,及吧每一个点都向其他点走一遍,dfs里多传最大最小值就行了,这样应该60,我却只有40。然后我把max,min改成if后就60了。
第三点,考试时想到一个方法,我们只需要求每一条边作为最大路径,最小路径出现的次数即可,但是朴素的方法求很慢,每一条边求一次就要n,最后依旧是n^2,没有区别。正解也是这样写的,但是再求边的使用数量上用并查集写。先将边排个序,从小到大,每次先求最大的,然后把这条边两边的点合并成一个点计算。正确性在于排序后下次访问的边肯定比之前的边要短,那么可以直接使用。这是对于求最小边,最大边反一下即可。
以下是图示
原图
合并一条边后

#include<bits/stdc++.h>
#define M 100005
using namespace std;
struct node{int x,y,z;}A[M];
bool cmp(node x,node y){return x.z>y.z;}
int fa[M],cnt[M];//fa[]是父亲节点,cnt是求合并后这个点代表着几个点
int Find(int x){return x==fa[x]?x:fa[x]=Find(fa[x]);}
int main(){
    int n;
    scanf("%d",&n);
    for(int i=1;i<n;i++)scanf("%d%d%d",&A[i].x,&A[i].y,&A[i].z);
    sort(A+1,A+n,cmp);//按边权从小到大
    for(int i=1;i<=n;i++)fa[i]=i,cnt[i]=1;//初始化
    long long Max=0,Min=0;
    for(int i=1;i<n;i++){
        int x=Find(A[i].x),y=Find(A[i].y);
        Min+=(1LL)*A[i].z*cnt[x]*cnt[y];
        fa[x]=y;
        cnt[y]+=cnt[x];
    }
    for(int i=1;i<=n;i++)fa[i]=i,cnt[i]=1;
    for(int i=n-1;i>=1;i--){//循环反过来,避免一次排序
        int x=Find(A[i].x),y=Find(A[i].y);
        Max+=(1LL)*A[i].z*cnt[x]*cnt[y];
        fa[x]=y;
        cnt[y]+=cnt[x];
    }
    printf("%lld\n",Max-Min);
    return 0;
}

这样就可以n logn完成

大学生参加学科竞有着诸多好处,不仅有助于个人综合素质的提升,还能为未来职业发展奠定良好基础。以下是一些分析: 首先,学科竞是提高专业知识和技能水平的有效途径。通过参与竞,学生不仅能够深入学习相关专业知识,还能够接触到最新的科研成果和技术发展趋势。这有助于拓展学生的学科视野,使其对专业领域有更深刻的理解。在竞过程中,学生通常需要解决实际问题,这锻炼了他们独立思考和解决问题的能力。 其次,学科竞培养了学生的团队合作精神。许多竞项目需要团队协作来完成,这促使学生学会有效地与他人合作、协调分工。在团队合作中,学生们能够学到如何有效沟通、共同制定目标和分工合作,这对于日后进入职场具有重要意义。 此外,学科竞是提高学生综合能力的一种途径。竞项目通常会涉及到理论知识、实际操作和创新思维等多个方面,要求参者具备全面的素质。在竞过程中,学生不仅需要展现自己的专业知识,还需要具备创新意识和解决问题的能力。这种全面的综合能力培养对于未来从事各类职业都具有积极作用。 此外,学科竞可以为学生提供展示自我、树立信心的机会。通过比的舞台,学生有机会展现自己在专业领域的优势,得到他人的认可和赞誉。这对于培养学生的自信心和自我价值感非常重要,有助于他们更加积极主动地投入学习和未来的职业生涯。 最后,学科竞对于个人职业发展具有积极的助推作用。在竞中脱颖而出的学生通常能够引起企业、研究机构等用人单位的关注。获得竞奖项不仅可以作为个人履历的亮点,还可以为进入理想的工作岗位提供有力的支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值