复旦大学计算机机试

复旦大学计算机机试

笔者最近打算刷一下各大高校的机试题,暂时不详细分类(可能是夏令营,预推免,也可能是考研机试。很有可能不全)

就按照学校分类一下:

先从最简单的复旦刷起。

题目来源是一个名叫N诺的网站,大家可以上去自己玩玩。

N诺

可自行注册一个账号

在这里插入图片描述

邀请码为:noobdream

题一 :求众数

在这里插入图片描述

分析:计数类首先想到Hash表,发现没有数字的取值范围,就老老实实用map。

因为c++的map有序,遍历一次就可以找到较小的那个众数。(不要用unordered_map)

#include <bits/stdc++.h>

using namespace std;

int main()
{
    int n;
    cin>>n;
    int a[n];
    map<int,int> m; //默认按照a[i]的大小排序
    for(int i=0;i<n;i++){
        cin>>a[i];
        m[a[i]]++;
    }
    int maxcnt=0,res=0;
    for(auto& it:m){
        if(it.second>maxcnt){
            res=it.first;
            maxcnt=it.second;
        }
    }
    cout<<res<<endl;
    return 0;
}

题二:解一元一次方程

在这里插入图片描述

#include <iostream>

using namespace std;

int main()
{
    string s;
    cin>>s;
    int sumx=0; //记录x前系数和
    int sumd=0;//记录常数和
    int num=0;
    int flag=1; //正负号
    int reve=1;//等号左右边
    int len=s.size();
    for(int i=0;i<len;i++){
        if(isdigit(s[i])){
            num=10*num+s[i]-'0';
        }

        if(s[i]=='x'){
            if(num==0) num=1;//x前没有缺省系数
            sumx+=num*flag*reve;
            num=0;
        }

        if(s[i]=='+'){
            sumd+=num*flag*reve;
            flag=1; //正号
            num=0; //为下一轮系数提取清零

        }

        if(s[i]=='-'){
            sumd+=num*flag*reve;
            flag=-1;
            num=0;
        }

        if(s[i]=='='){
            sumd+=num*flag*reve;
            flag=1;
            reve=-1;
            num=0;
        }
    }
    sumd+=num*flag*reve; //字符串末尾是没有结束符的,要再累计一次

    if(sumx==0&&sumd==0) cout<<"infinite solutions"<<endl;
    else if(sumx==0) cout<<"no solution"<<endl;
    else cout<<"x="<<(double)-sumd/sumx<<endl; //sumx * x+sumd=0 ,x=-sumd/sumx
    return 0;
}

题三:骨牌

在这里插入图片描述

#include <iostream>

using namespace std;
/*
n=1 , 1
n=2 , 2
n=3 , 3
n=4 , 5
发现规律:f(n)=f(n-1)+f(n-2)  也可以从排放形状入手
带入知道,f(6)=13
*/


int main()
{
    int n;
    cin>>n;
    if(n<=2){
         cout<<n<<endl;
         return 0;
    }
    int pre2=1;
    int pre1=2;
    int ans;
    for(int i=3;i<=n;i++){
        ans=(pre1+pre2)%999983;
        pre2=pre1;
        pre1=ans;
    }
    cout<<ans<<endl;
    return 0;
}

题四:集合交并

在这里插入图片描述

#include <bits/stdc++.h>

using namespace std;

int main()
{
    int n,m;
    cin>>n>>m;
    int a[n],b[m];
    set<int> s1;
    for(int i=0;i<n;i++){
        cin>>a[i];
        s1.insert(a[i]);
    }
    set<int> s2,s3(s1);
    for(int i=0;i<m;i++){
        cin>>b[i];
        if(s1.count(b[i])){ //s2用来存交集
            s2.insert(b[i]);
        }else{
            s3.insert(b[i]);//s3用来存并集
        }
    }
    cout<<s2.size()<<" "<<s3.size()<<endl;

    return 0;
}

题五:约数求和

在这里插入图片描述

#include <iostream>

using namespace std;
/*
1 : 1
2 : 1 2
3 : 1 3
4 : 1 2 4
5 : 1 5
6 : 1 2 3 6
7 : 1 7
通过以上规律发现:1出现7/1次,2出现7/2次,3出现7/3次
i 出现 n/i次
*/


int main()
{
    int n;
    cin>>n;
    long long ans=0;
    for(int i=1;i<=n;i++){
        ans+=(i)*(n/i);  
    }
    cout<<ans<<endl;
    return 0;
}

题六:求交点

在这里插入图片描述

#include <bits/stdc++.h>

using namespace std;
/*
y=(x-x1)*(y2-y1)/(x2-x1)+y1
y=(x-x3)*(y4-y3)/(x4-x3)+y3

解方程即可,但是注意,用乘积,少用除,防止出现除0. k1,k3不要算出来,展开了做
*/
int main()
{
    int x1,y1,x2,y2;
    int x3,y3,x4,y4;
    cin>>x1>>y1>>x2>>y2;
    cin>>x3>>y3>>x4>>y4;
    int a0=(y2-y1)*(x4-x3)-(y4-y3)*(x2-x1);
    if(a0==0){
        cout<<"Parallel or coincident"<<endl;
    }else{

        int a1=(x4-x3)*(y2-y1)*x1;
        int a2=(x2-x1)*(y4-y3)*x3;
        int a3=(x4-x3)*(x2-x1)*(y3-y1);
        double x=(double)(a1-a2+a3)/a0;
        double y=(x-x1)*(y2-y1)/(x2-x1)+y1;
       printf("%.2f %.2f",x,y);

    }
    return 0;
}

题七:长方形中的正方形

在这里插入图片描述

#include <iostream>

using namespace std;

/*
刚开始一看,有点儿像辗转相除的味道。
用递归写就好
递归函数recur(n,m)表示求的长方形长为n,宽为m的正方形个数
recur(n,m)=
1, n==m 
1+recur(n-m,m),n>m
1+recur(n,m-n),n<m


递归三步走:
1.确定递归函数的意义
2.确定递归的方程
3.确定递归的初始条件

*/
int recur(int n,int m){
    if(n==m) return 1;
    else{
        if(n<m) return 1+recur(n,m-n);
        else return 1+recur(m,n-m);

    }

}

int main()
{
    int n,m;
    cin>>n>>m;
    cout<<recur(n,m)<<endl;
    return 0;
}

题八:a与b得到c

在这里插入图片描述

#include <bits/stdc++.h>

using namespace std;
/*
送分不解释,如果是经过有限次四则运算,就变成了dfs的题了
*/
int main()
{
    int a,b,c;
    cin>>a>>b>>c;
    set<double> s;
    s.insert(a+b);
    s.insert(a-b);
    s.insert(b-a);
    s.insert(a*b);
    s.insert((double)a/b);
    s.insert((double)b/a);
    if(s.count(c)) cout<<"YES"<<endl;
    else cout<<"NO"<<endl;
    return 0;
}

题九:相隔天数

在这里插入图片描述

#include <bits/stdc++.h>

using namespace std;
/*
日期类问题,常规模拟,注意相隔多少天,要取绝对值。
这里没说错误提示,我就没有对日期进行错误判断了。
*/
bool isLeapYear(int year){
    return (year%4==0&&year%100!=0)||year%400==0;
}

int month_day[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};

int fromDays(int year,int month,int day){  //自1970:01:01
    int days=0;
    for(int i=1970;i<year;i++){
        if(isLeapYear(i)) days+=366;
        else days+=365;
    }
    for(int i=1;i<month;i++){
        days+=month_day[i];
    }
    if(isLeapYear(year)&&month>2) days++;
    days+=day;
    return days;
}

int main()
{
    string s;
    cin>>s;
    int len=s.size();
    int year=0;
    int month=0;
    int day=0;
    for(int i=0;i<len;i++){
        if(i<4){
            year=10*year+s[i]-'0';
        }else if(i<6){
            month=10*month+s[i]-'0';
        }else{
            day=10*day+s[i]-'0';
        }
    }
    cout<<abs(fromDays(year,month,day)-fromDays(2019,2,5))<<endl;

    return 0;
}

题十:最大连续子序列

在这里插入图片描述

#include <bits/stdc++.h>
/*
非常简单的一个dp,
dp[i]表示以a[i]结尾的最大连续子序列
dp[i]=
dp[i-1]+a[i],dp[i-1]>0
a[i] ,dp[i-1]<=0

最终答案res=max(res,dp[i])所有dp[i]的最大值
因为dp[i]只与dp[i-1]有关,于是可以压缩数组,为一个cur变量即可
*/
using namespace std;

int main()
{
    int n;
    cin>>n;
    int a[n];
    int cur=0;
    int res=INT_MIN;
    for(int i=0;i<n;i++){
        cin>>a[i];
        cur=cur>0?cur+a[i]:a[i];
        res=max(cur,res);
    }
    cout<<res<<endl;
    return 0;
}

题十一:有向树形态

在这里插入图片描述

#include <iostream>

using namespace std;

/*
n=0, f(0)=1;
n=1 ,f(1)=1
n=2, f(2)=2
n=3, f(3)=f(2)+f(1)*f(1)+f(2)

卡特兰数
f(n)=f(n-1)f(0)+f(n-2)f(1)+ ...+f(1)f(n-2)+f(0)f(n-1)

f(n)=(2n)!/((n)!*(n+1)!)
*/

long long f[21];

int main()
{
    int n;
    cin>>n;
    f[0]=1;
    f[1]=1;
    for(int i=2;i<=n;i++){
        for(int j=1;j<=i;j++){
            f[i]+=f[i-j]*f[j-1];
        }
    }
    cout<<f[n]<<endl;
    return 0;
}

2020夏令营机试(图片来源网上)

img

题一:拓扑排序模板

/*
测试用例:
4
1 0
2 0
3 1
3 2
-1 -1//结束标志
*/

#include <bits/stdc++.h>

using namespace std;


vector<int> topo(int n,vector<vector<int>>& prerequist){
    vector<int> res;
    vector<int> indegrees(n);  //入度表
    vector<vector<int>> adj(n); //邻接表
    queue<int> zero;//度数为0的队列
    for(vector<int> tmp:prerequist){
        indegrees[tmp[0]]++;
        adj[tmp[1]].push_back(tmp[0]);
    }
    for(int i=0;i<n;i++){
        if(indegrees[i]==0) zero.push(i);
    }
    while(!zero.empty()){
        int tmp=zero.front();
        zero.pop();
        res.push_back(tmp);
        for(int j=0;j<adj[tmp].size();j++){
            if(--indegrees[adj[tmp][j]]==0) zero.push(adj[tmp][j]);
        }
    }
    return res.size()==n?res:vector<int>{};




    return res;
}


int main()
{
    int n;
    cin>>n;  //输入没有进行太多处理,不是重点
    vector<vector<int>> prerequist;
    int x,y;
    while(cin>>x>>y) {
        vector<int> tmp;
        tmp.push_back(x);
        tmp.push_back(y);
        prerequist.push_back(tmp);
        if(x==-1){
            prerequist.pop_back();
            break;
        }
    }
    vector<int> res=topo(n,prerequist);
    for(int tmp:res){
        cout<<tmp<<" ";
    }
    cout<<endl;
    return 0;
}

题二:动规,等有时间再更新

备注:复旦这边题可以说,比较基础,大一的c语言学好都能做,有一些基础的数学找规律题。

可能是文理学校的缘故。

相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页