2020浙大軟院預推免機試復盤


總結:題目很難讀,只能靠樣例理解,也不知道代碼寫得對不對,萬幸數據不太強。

A

給一個多項式的因式分解的形式,比如P=(x-a1)(x-a2)...(x-an),要求出多項式除了x^n之外,其他項的系數。n<=10。

比如x^2,就是選2項共享一個x,其他項貢獻ai乘起來,所以dfs搜一下。

//
// Created by zxc on 2020/9/23.
//
#include <bits/stdc++.h>
using namespace std;
int n;
int r[15];
int res[15];
bool vis[15];
void dfs(int i,int now,int tar){
    if(i==n+2){
        return;
    }
    if(now==tar){
        int t=1;
        for(int j=1;j<=n;j++){
            if(!vis[j]){
                t=t*r[j];
            }
        }
        res[tar]+=t;
        return;
    }
    vis[i]=true;
    dfs(i+1,now+1,tar);
    vis[i]=false;
    dfs(i+1,now,tar);
}
int main(){
//    freopen("in.txt","r",stdin);
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&r[i]);
        r[i]=-r[i];
    }
    for(int i=n-1;i>=0;i--){
        dfs(1,0,i);
    }
    for(int i=n-1;i>=0;i--){
        printf("%d%c",res[i],i==0?'\n':' ');
    }
    return 0;
}

B

給定三個數集,大小是1e4,在三個集合里分別找三個數a,b和c,使得|a-b|+|b-c|+|c-a|最小。

這題一開始沒思路放了,思路一開始不對,一直想着正負正負和大小關系,后來想枚舉枚舉,就想到枚舉中間的數,再一看,發現如果枚舉中間的數,那表達式其實就是左右兩個數的距離的2倍。

所以把三個數集排一下序,然后按bac,cab,abc,cba,acb,bca這六種情況,分別枚舉中間的值,然后lower_bound找到左右兩邊最近的一個,再注意判掉一些邊界情況。題目說如果有多個輸出三元組最大的,可是並沒有定義什么是三元組最大的???猜了一下是和最大,就過了。

代碼是我最喜歡的ctrl c+v

//
// Created by zxc on 2020/9/23.
//
#include <bits/stdc++.h>
using namespace std;
const int N=1e4+50;
vector<int> a,b,c;
int as,bs,cs,x;
int ans_a,ans_b,ans_c;
struct node{
    int a,b,c;
    bool operator <(const node& rhs)const{
        return (a+b+c)<(rhs.a+rhs.b+rhs.c);
    }
};
int main(){
//    freopen("in.txt","r",stdin);
    scanf("%d%d%d",&as,&bs,&cs);
    for(int i=0;i<as;i++){
        scanf("%d",&x);
        a.push_back(x);
    }
    for(int i=0;i<bs;i++){
        scanf("%d",&x);
        b.push_back(x);
    }
    for(int i=0;i<cs;i++){
        scanf("%d",&x);
        c.push_back(x);
    }
    sort(a.begin(),a.end());
    sort(b.begin(),b.end());
    sort(c.begin(),c.end());
    int ans=0x3f3f3f3f;
    // cab
    for(int i=0;i<as;i++){
        int mid=a[i];
        int cx=lower_bound(c.begin(),c.end(),mid)-c.begin();
        if(cx==cs){
            cx--;
        }else if(c[cx]!=mid){
            if(cx==0){
                continue;
            }
            cx--;
        }
        int cc=c[cx];
        int bd=lower_bound(b.begin(),b.end(),mid)-b.begin();
        if(bd==bs){
            continue;
        }
        int bb=b[bd];
        int tmp=2*(bb-cc);
        if(tmp<ans){
            ans=tmp;
            ans_a=mid;
            ans_b=bb;
            ans_c=cc;
        }else if(tmp==ans){
            node now={ans_a,ans_b,ans_c};
            node tp={mid,bb,cc};
            if(now<tp){
                ans_a=mid;
                ans_b=bb;
                ans_c=cc;
            }
        }
    }
    // bac
    for(int i=0;i<as;i++){
        int mid=a[i];
        int bx=lower_bound(b.begin(),b.end(),mid)-b.begin();
        if(bx==bs){
            bx--;
        }else if(b[bx]!=mid){
            if(bx==0){
                continue;
            }
            bx--;
        }
        int bb=b[bx];
        int cd=lower_bound(c.begin(),c.end(),mid)-c.begin();
        if(cd==cs){
            continue;
        }
        int cc=c[cd];
        int tmp=2*(cc-bb);
        if(tmp<ans){
            ans=tmp;
            ans_a=mid;
            ans_b=bb;
            ans_c=cc;
        }else if(tmp==ans){
            node now={ans_a,ans_b,ans_c};
            node tp={mid,bb,cc};
            if(now<tp){
                ans_a=mid;
                ans_b=bb;
                ans_c=cc;
            }
        }
    }
    // abc
    for(int i=0;i<bs;i++){
        int mid=b[i];
        int ax=lower_bound(a.begin(),a.end(),mid)-a.begin();
        if(ax==as){
            ax--;
        }else if(a[ax]!=mid){
            if(ax==0){
                continue;
            }
            ax--;
        }
        int aa=a[ax];
        int cd=lower_bound(c.begin(),c.end(),mid)-c.begin();
        if(cd==cs){
            continue;
        }
        int cc=c[cd];
        int tmp=2*(cc-aa);
        if(tmp<ans){
            ans=tmp;
            ans_a=aa;
            ans_b=mid;
            ans_c=cc;
        }else if(tmp==ans){
            node now={ans_a,ans_b,ans_c};
            node tp={aa,mid,cc};
            if(now<tp){
                ans_a=aa;
                ans_b=mid;
                ans_c=cc;
            }
        }
    }
    // cba
    for(int i=0;i<bs;i++){
        int mid=b[i];
        int cx=lower_bound(c.begin(),c.end(),mid)-c.begin();
        if(cx==cs){
            cx--;
        }else if(c[cx]!=mid){
            if(cx==0){
                continue;
            }
            cx--;
        }
        int cc=c[cx];
        int ad=lower_bound(a.begin(),a.end(),mid)-a.begin();
        if(ad==as){
            continue;
        }
        int aa=a[ad];
        int tmp=2*(aa-cc);
        if(tmp<ans){
            ans=tmp;
            ans_a=aa;
            ans_b=mid;
            ans_c=cc;
        }else if(tmp==ans){
            node now={ans_a,ans_b,ans_c};
            node tp={aa,mid,cc};
            if(now<tp){
                ans_a=aa;
                ans_b=mid;
                ans_c=cc;
            }
        }
    }
    // acb
    for(int i=0;i<cs;i++){
        int mid=c[i];
        int ax=lower_bound(a.begin(),a.end(),mid)-a.begin();
        if(ax==as){
            ax--;
        }else if(a[ax]!=mid){
            if(ax==0){
                continue;
            }
            ax--;
        }
        int aa=a[ax];
        int bd=lower_bound(b.begin(),b.end(),mid)-b.begin();
        if(bd==bs){
            continue;
        }
        int bb=b[bd];
        int tmp=2*(bb-aa);
        if(tmp<ans){
            ans=tmp;
            ans_a=aa;
            ans_b=bb;
            ans_c=mid;
        }else if(tmp==ans){
            node now={ans_a,ans_b,ans_c};
            node tp={aa,bb,mid};
            if(now<tp){
                ans_a=aa;
                ans_b=bb;
                ans_c=mid;
            }
        }
    }
    // bca
    for(int i=0;i<cs;i++){
        int mid=c[i];
        int bx=lower_bound(b.begin(),b.end(),mid)-b.begin();
        if(bx==bs){
            bx--;
        }else if(b[bx]!=mid){
            if(bx==0){
                continue;
            }
            bx--;
        }
        int bb=b[bx];
        int ad=lower_bound(a.begin(),a.end(),mid)-a.begin();
        if(ad==as){
            continue;
        }
        int aa=a[ad];
        int tmp=2*(aa-bb);
        if(tmp<ans){
            ans=tmp;
            ans_a=aa;
            ans_b=bb;
            ans_c=mid;
        }else if(tmp==ans){
            node now={ans_a,ans_b,ans_c};
            node tp={aa,bb,mid};
            if(now<tp){
                ans_a=aa;
                ans_b=bb;
                ans_c=mid;
            }
        }
    }
    printf("MinD(%d, %d, %d) = %d\n",ans_a,ans_b,ans_c,ans);
    return 0;
}

C

題意也是很難讀。。。n個人,每個人有一個分數,然后每個人有一個合照,合照上都是同校的隊友,然后現在要統計所有學校的總分按從高到低排序,每個學校的id就是最小的那個學生id,分數相同按隊員數量從小到大排序,數量相同按id從小到大排序。

id是4位數,所以不用離散化,就先並查集合並一下,然后暴力枚舉全部出現過的id,更新每個學校隊伍的最小學生id,以及統計數量和總分,然后去重,排序。最后輸出記得要%4d。

//
// Created by zxc on 2020/9/23.
//
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+50;
int p[N];
int n,k,id[N],sc[N],x;
vector<int> fr[N];
int find(int x){
    return x==p[x]?p[x]:p[x]=find(p[x]);
}
int vis[N];
struct node{
    int scid;
    int allsco;
    int num;
    int fir=true;
    bool operator<(const node& rhs)const{
        if(allsco!=rhs.allsco){
            return allsco>rhs.allsco;
        }else{
            if(num!=rhs.num){
                return num<rhs.num;
            }else{
                return scid<rhs.scid;
            }
        }
    }
    bool operator ==(const node& rhs)const{
        return (allsco==rhs.allsco && num==rhs.num && scid==rhs.scid && fir==rhs.fir);
    }
}ans[N];
int main(){
//    freopen("in.txt","r",stdin);
    scanf("%d",&n);
    for(int i=0;i<=9999;i++){
        p[i]=i;
    }
    for(int i=1;i<=n;i++){
        scanf("%d",&id[i]);
        vis[id[i]]=true;
        scanf("%d",&k);
        for(int j=0;j<k;j++){
            scanf("%d",&x);
            vis[x]=true;
            int fa=find(id[i]);
            int fb=find(x);
            fr[id[i]].push_back(x);
            if(fa!=fb){
                p[fa]=fb;
            }
        }
        scanf("%d",&sc[id[i]]);
    }
    for(int i=0;i<=9999;i++){
        if(!vis[i]){
            continue;
        }
        int fa=find(i);
        ans[fa].allsco+=sc[i];
        ans[fa].num++;
        if(ans[fa].fir){
            ans[fa].scid=i;
            ans[fa].fir=false;
        }else{
            ans[fa].scid=min(ans[fa].scid,i);
        }
    }
    vector<node> v;
    for(int i=0;i<=9999;i++){
        if(!vis[i]){
            continue;
        }
        int fa=find(i);
        v.push_back(ans[fa]);
    }
    sort(v.begin(),v.end());
    v.erase(unique(v.begin(),v.end()),v.end());
    int siz=v.size();
    printf("%d\n",siz);
    for(int i=0;i<siz;i++){
        printf("%04d %d %d\n",v[i].scid,v[i].num,v[i].allsco);
    }
    return 0;
}

D

題意不知道在講啥。。。連個中心詞coupon都看不懂,估計是優惠還是啥,反正分析樣例就是有n個商品,n個級別的優惠,買一個商品可以得到一個優惠(顯然是選優惠最高的),同理買同一種的第二個商品就只能選第二檔優惠,如果買超過n個同類商品,就沒有優惠了。有d美元,問怎么買可以買到最多的商品。

這題卡了將近一個小時。。。最后靈光一現想到面經里面看過排序幾個有序大文件里的數字,就堆里只要放每個文件的一個指針,然后拿完一個就把對應文件的指針移到下一個數。

所以同理,維護一個堆,先把買每一種商品用第一檔優惠真正需要花的錢放堆里,然后拿出最小的,把對應的商品使用第二檔優惠的花的錢放進去,以此類推,直到錢不夠了。

//
// Created by zxc on 2020/9/23.
//
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+50;
const int D=1e6+50;
int n,d;
int a[N],b[N];
bool cmp(int x,int y){
    return x>y;
}
struct node{
    int i,j,cos;
    bool operator <(const node& rhs)const{
        return cos>rhs.cos;
    }
};
int main(){
//    freopen("in.txt","r",stdin);
    scanf("%d%d",&n,&d);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    for(int i=1;i<=n;i++){
        scanf("%d",&b[i]);
    }
    sort(a+1,a+1+n,cmp);
    sort(b+1,b+1+n,cmp);
    priority_queue<node> q;
    for(int i=1;i<=n;i++){
        q.push(node{i,1,a[i]-b[1]});
    }
    int ans=0;
    int res=d;
    while(!q.empty()){
        node t=q.top();
        q.pop();
        res-=t.cos;
        if(res<0){
            res+=t.cos;
            break;
        }
        ans++;
        if(t.j+1<=n){
            q.push(node{t.i,t.j+1,a[t.i]-b[t.j+1]});
        }else{
            // 考試時沒寫上這個,也過了
            q.push(node{t.i,t.j+1,a[t.i]});
        }
    }
    printf("%d %d\n",ans,res);
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM