2020年十二月ccf-csp认证总结(内附个人题解)

吐槽一下这个在线评测功能,平均四十分钟才能看到提交结果。。
本次成绩为100+100+0+30+20,最后两道题都是骗的分
在这里插入图片描述

在这里插入图片描述
(提醒自己附代码的神奇图片,希望寒假有时间把没做出来的题目也再做一遍)

csp官网更新出题目后,有路过的可以提醒我把题目加上(也可以随手点个关注啊),以下为个人回忆和csp网站所下载的当时提交的代码:

第一题

在这里插入图片描述

送分题,输入俩数组a[n],b[n],求a[i]*b[i]从1-n的求和

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n,i,j;
    cin>>n;
    int w[n],score[n];
    for(i=0;i<n;i++)
    {
        cin>>w[i]>>score[i];
    }
    int sum=0;
    for(i=0;i<n;i++)
    {
        sum+=w[i]*score[i];
    }
    if(sum<0) sum=0;
    cout<<sum<<endl;
}

第二题

HM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ0MTA5OTgy,size_16,color_FFFFFF,t_70)
上面的代码是当时考场提交的,与评测网站的样例并不完全相同
评测网站给的样例涉及了相同分数下,有人挂科有人不挂科的情况。。(印象里考场上是没说这点)
可以对照csp网站上的样例1,看看新版本代码的改进在哪

#include<bits/stdc++.h>
using namespace std;
struct stu
{
    int y;
    int result;
};
map<int,int> mp;
bool cmp(stu &s1,stu &s2)
{
    return s1.y<s2.y;
}
int main()
{
    ios::sync_with_stdio(0);
    int n,i,j;
    cin>>n;
    stu s[n];
    for(i=0;i<n;i++)
    {
        cin>>s[i].y>>s[i].result;
        mp[s[i].y]++;
    }
    sort(s,s+n,cmp);
    int big=0;
    int sum=0;
    for(i=0;i<n;i++)
    {
        if(s[i].result==1)
        {
            sum++;
        }
    }
    int m=sum;
    for(i=0;i<n;i++)
    {
        for(j=0;j<mp[(s[i].y)];j++)
        {
        if(s[i+j].result==0) sum++;
        else sum--;
        }
        if(m<=sum)
        {
            m=sum;
            big=i+mp[s[i].y];
        }
        i+=mp[s[i].y]-1;
    }
    cout<<s[big].y<<endl;
}

有点小坑,是说在第一题的基础上,求一个最优阙值,本着前两题很简单的原则写了两层循环,过了好久才发现只得了70分。。

最后的思路就是用结构体存储y(分数)和prey(预测结果,1为正确,0为错误)

按照分数从小到大的顺序快排(时间复杂度为nlogn)

然后这个问题(那个求和)可以转化成左边0的个数+右边1的个数,因为左边元素肯定小于他,右边元素肯定大于他,先假设我们位于a[0]的左边,统计出1的个数,然后从i=0开始,依次将a[i]从右边放到我们的左边

所以当a[i]预测值为0时,得分会加1,预测值为1时,会减1
记录一个最大值,将其对应的阙值输出即可

实际上是用排序的方式,减少了重复多余的比较

#include<bits/stdc++.h>
using namespace std;
struct stu
{
    int y;
    int result;
};
bool cmp(stu &s1,stu &s2)
{
    return s1.y<s2.y;
}
int main()
{
    ios::sync_with_stdio(0);
    int n,i,j;
    cin>>n;
    stu s[n];
    for(i=0;i<n;i++)
    {
        cin>>s[i].y>>s[i].result;
    }
    sort(s,s+n,cmp);
    int big=0;
    int sum=0;
    for(i=0;i<n;i++)
    {
        if(s[i].result==1)
        {
            sum++;
        }
    }
    int m=sum;
    for(i=0;i<n;i++)
    {
        if(s[i].result==0) sum++;
        else sum--;
        if(m<=sum)
        {
            m=sum;
            big=i+1;
        }
    }
    cout<<s[big].y<<endl;
}

第三题

没写出来,确实麻烦

在这里插入图片描述

第四题

在这里插入图片描述
在这里插入图片描述

只做了前30%样例点,因为注意到前30%为一条链,且保证输入的两个结点u,v满足v=u+1,那不就可以用数组存储了吗!

最短路径肯定是从最左边开始,经过需要这种食材的酒店,最终送到最右边(或最右送到最左,因为这样不用掉头重复某一段路径)

然后就很普通的求数组的子序列和,比较k个子序列和的最大值就是所求值。

#include<bits/stdc++.h>
using namespace std;
int wr[105]= {0},wl[105]= {0},n;
int main()
{
    int m,k;
    cin>>n>>m>>k;
    int f[n][k],i,j;
    for(i=0; i<n; i++)
        for(j=0; j<k; j++)
        {
            cin>>f[i][j];
        }

    int s=0,e=0;
    for(i=0; i<n-1; i++)
    {
        cin>>s>>e;
        cin>>wr[s-1];
    }
    int m0=0;
    for(i=0; i<k; i++)
    {
        int l=-1,r=-1,sum=0;
        for(j=0; j<n; j++)
        {
            if(f[j][i]==1&&l==-1)
            {
                l=j;
            }
            if(f[j][i]==1)
            {
                r=j;
            }
        }
        for(j=l; j<r; j++)
        {
            sum+=wr[j];
        }
       // cout<<l<<' '<<r<<' '<<k<<' '<<sum<<endl;
        if(sum>m0)
        {

            m0=sum;
        }

    }
    cout<<m0<<endl;

}

第五题

在这里插入图片描述

感觉应该是用[a,b,size]的某种结构存储a到b的序列大小?类似于前几次的一个稀疏矩阵的题目。

但是时间不太够了(就不应该做第三题),于是拿long存储数据,每一步运算完都对1e9+7求余,听同学说可以骗20分,因为走的时候这题还没出分,所以要等出成绩了

#include<bits/stdc++.h>
using namespace std;
long x[100005]={0},y[100005]={0},z[100005]={0};
long a,b,c;
int main()
{
   ios::sync_with_stdio(0);
   int n,m,i,j,call,l,r;
   cin>>n>>m;
   for(i=0;i<m;i++)
   {
       cin>>call>>l>>r;
       if(call==1)
       {
           cin>>a>>b>>c;
           for(j=l;j<=r;j++)
           {
               x[j]=(x[j]+a)%1000000007;
               y[j]=(y[j]+b)%1000000007;
               z[j]=(z[j]+c)%1000000007;
           }
       }
       else if(call==2)
       {
           long k;
           cin>>k;
           for(j=l;j<=r;j++)
           {
               x[j]=(x[j]*k)%1000000007;
               y[j]=(y[j]*k)%1000000007;
               z[j]=(z[j]*k)%1000000007;
           }
       }
       else if(call==3)
       {
           long long temp;
           for(j=l;j<=r;j++)
           {
               temp=x[j];
               x[j]=y[j];
               y[j]=z[j];
               z[j]=temp;
           }
       }
       else if(call==4)
       {
           long long x0=0,y0=0,z0=0;
           for(j=l;j<=r;j++)
           {
               x0=(x0+x[j])%1000000007;
               y0=(y0+y[j])%1000000007;
               z0=(z0+z[j])%1000000007;
           }
           cout<<((x0*x0)+(y0*y0)+(z0*z0))%1000000007<<endl;
       }
   }
   return 0;
}
  • 12
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 29
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 29
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值