快手2020校园招聘秋招笔试--工程C试卷 (编程题题解全)

1.病毒检测

滑动窗口题

例子:

2

0101010(第一位下标为1)

1)找到第一个最短的满足k条件的子串,即s[2~4],l=2,r=4

2)找出这个子串左右连续的0的个数,分别为a,b,则对于这个子串的贡献为(a+1)*(b+1)

3)之后就是滑动窗口,r到下一个1的位置,l向右移动到第一个一的位置,重复2)计算贡献

#include 
using namespace std;
typedef long long ll;
const int maxn=1000050;
char s[maxn];
int main()
{
    ll n,k;
    scanf("%lld",&k);
    scanf("%s",s+1);
    n=strlen(s+1);
    ll tmp=0,tp=0,fi=0,se=0,l=1,r=0,ans=0;
    if(k==0){
        for(int i=1;i<=n;i++){
            if(s[i]=='0'){
                tmp++;
                if(i==n) ans+=tmp*(tmp+1)/2;
            }
            else{
                ans+=tmp*(tmp+1)/2;
                tmp=0;
            }
        }
        printf("%lld\n",ans);
        return 0;
    }
 
    for(int i=1;i<=n;i++){
        if(s[i]=='1'){
            tmp++;
        }
        if(tmp==k){
            r=i;
            break;
        }
    }
    if(r==0){
        printf("0\n");
        return 0;
    }
    tp=tmp=1;
 
    r++;
    while(s[r]=='0'&&r<=n) tp++,r++;
    while(s[l]=='0') tmp++,l++;
    ans+=tmp*tp;
    //printf("%lld %lld %lld %lld %lld\n",l,r,ans,tmp,tp);
    //printf("!%lld\n",ans);
    while(r<=n){
        l++;r++;
        tmp=tp=1;
        while(s[l]=='0'){
            tmp++;l++;
        }
        while(s[r]=='0'&&r<=n) tp++,r++;
        ans+=tmp*tp;
        //printf("%lld\n",ans);
    }
    printf("%lld\n",ans);
    return 0;
}

考试成绩

每道题的答案为该题最多人选的答案

#include
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define dep(i, j, k) for(int i = k; i >= j; i--)
#define pb push_back
using namespace std;
const double eps=1e-8;
typedef long long ll;
const int maxn = 1050;
char s[maxn][maxn];
int num[5];
ll b[maxn];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%s",s[i]+1);
    }
    for(int j=1;j<=m;j++) scanf("%lld",&b[j]);
    ll ans=0;
    for(int i=1;i<=m;i++){
        memset(num,0,sizeof(num));
        for(int j=1;j<=n;j++){
            num[s[j][i]-'A']++;
        }
        int mx=0;
        for(int i=0;i<5;i++) mx=max(mx,num[i]);
        ans+=b[i]*mx;
    }
    printf("%lld\n",ans);
}

石头碰撞

01背包。这道题的思路需要转化一下,其实这道题要求的就是把这些石头分成两部分,相差的最小值。可以感性理解下。

这样子就是最基础的01背包了,看f[i] i这个容量能不能凑出来

#include 
using namespace std;
typedef long long ll;
const int maxn=10050;
int f[maxn],a[maxn];
int main()
{
    int n;
    scanf("%d",&n);
    int sum=0;
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),sum+=a[i];
    f[0]=1;
    for(int i=1;i<=n;i++){
        for(int j=sum;j>=a[i];j--){
            f[j]|=f[j-a[i]];
        }
    }
    int ans=sum;
    for(int i=1;i<=sum;i++){
        if(f[i]){
            ans=min(ans,abs(i-(sum-i)));
        }
    }
    printf("%d\n",ans);
    return 0;
}

蓄水池大作战

刚看题以为很难,然后数据范围只有1000,直接暴力即可

#include
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define dep(i, j, k) for(int i = k; i >= j; i--)
#define pb push_back
using namespace std;
const double eps=1e-8;
typedef long long ll;
const int maxn = 1050;
vectorve[maxn];
int fa[maxn],a[maxn];
void dfs(int u,int f,int flag){
    fa[u]=f;
    a[u]=flag;
    for(auto v:ve[u]){
        if(v==f) continue;
        dfs(v,u,flag);
    }
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i

 

你可能感兴趣的:(校招,背包)