快手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 <bits/stdc++.h>
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<bits/stdc++.h>
#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 <bits/stdc++.h>
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<bits/stdc++.h>
#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;
vector<int>ve[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<n;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        ve[x].push_back(y);
        ve[y].push_back(x);
    }
    dfs(1,1,0);
    int q;
    scanf("%d",&q);
    while(q--){
        int op,x;
        scanf("%d%d",&op,&x);
        if(op==1){
            dfs(x,fa[x],1);
        }
        else if(op==2){
            while(fa[x]!=x){
                a[x]=0;
                x=fa[x];
            }
            a[1]=0;
        }
        else{
            if(a[x]) printf("1\n");
            else printf("0\n");
        }
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章