• 2018年北京大学软件工程学科夏令营上机考试


    2018年北京大学软件工程学科夏令营上机考试#

    题目链接
    密码:fighting
    总体题目难度不大,都是常规题。就看谁写的快了。

    A - 第K小最简真分数##

    这个题不是这次考试的题目,A应该是签到,由于没有找到原题,找到一个"题目类似"作为补充。但是这个应该比其他任何题目都难。

    题意:###

    给一个整数N,请你求出以N为分母的最简(既约)真分数中第K小的是多少 。
    $1 <= N <= 10000000000 且 1 <= K <= φ(N) $

    题解:###

    • 唯一分解定律分解出的质数不超过20个。
    • 1到x有因子y的树的个数为$frac xy $个。
    • 容斥定理去重。
    • 对于任何一个分母N,包含其唯一分解定理分解出来的质因子,就一定不是真分数,使用容斥定理计算包含至少一个质因子的个数。求第K大,一般想到二分,二分答案即可。

    代码:###

    #include <iostream>
    #include<stdio.h>
    #include<string>
    #include<cstring>
    using namespace std;
    #define ll long long
    ll a[2000],b[2000],tot;//a是因子乘积,b是代表奇偶。
    ll K,N,l,r,Mid,ans;
    ll prim[20],cnt;
    void divide(ll n){
        ll y=n;
        for(ll i=2;i*i<=n;i++){
            if(y%i==0)prim[cnt++]=i;
            while(y%i==0&&y)y/=i;
        }
        if(y>1)prim[cnt++]=y;
    }
    void dfs(ll x,int y,int num){
        if(y==cnt){//遍历到最后一个因子
            if(x==1)return ;
            a[tot]=x;b[tot++]=(num&1)?1:-1;
            return;
        }
        dfs(x*prim[y],y+1,num+1);
        dfs(x,y+1,num);
    }
    bool check(ll n){
        ll num=0;//与n不互质的个数
        for(ll i=0;i<tot;i++){
            num+=n/a[i]*b[i];
        }
        return n-num>=K;
    }
    int main()
    {
        cnt=0;
        tot=0;
        scanf("%lld%lld",&N,&K);
        divide(N);
        dfs(1,0,0);
        l=0;r=1e12;
        while(l<=r){
            Mid=(l+r)/2;
            if(check(Mid)){
                ans=Mid;
                r=Mid-1;
            }
            else l=Mid+1;
           //cout<<l<<"  "<<r<<endl;
        }
        printf("%lld
    ",ans);
        return 0;
    }
    
    

    B - n-gram串频统计##

    题意:###

    水题模拟

    题解:###

    暴力,使用map,可能写法比较麻烦

    代码:###

    #include <iostream>
    #include <string>
    #include <stdio.h>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <cmath>
    #include<map>
    using namespace std;
    map<string,int>map_cnt;
    map<string,int>map_rk;
    int main()
    {
        int n;
        cin>>n;
        string str;
        cin>>str;
        for(int i=0;i<=str.size()-n;i++){
            string temp="";
            for(int j=0;j<n;j++){
                temp+=str[i+j];
            }
            map_cnt[temp]++;
        }
        map<string,int>::iterator it;
        int cnt=0;
        for(it=map_cnt.begin();it!=map_cnt.end();it++){
            cnt=max(cnt,(*it).second);
        }
        if(cnt<2){
            cout<<"NO"<<endl;
            return 0;
        }
        int ans=0;
        for(it=map_cnt.begin();it!=map_cnt.end();it++){
            if((*it).second==cnt)ans++;
        }
        cout<<cnt<<endl;
         for(int i=0;i<=str.size()-n;i++){
            string temp="";
            for(int j=0;j<n;j++){
                temp+=str[i+j];
            }
            if(map_cnt[temp]==cnt){
                if(!map_rk.count(temp)){
                    cout<<temp<<endl;
                }
            map_rk[temp]++;
            }
        }
    
        return 0;
    }
    

    C - 垂直直方图##

    题意:###

    水题模拟

    题解:###

    暴力,读入一行可以使用gets,fgets,getline等函数。

    代码:###

    #include <iostream>
    #include <string>
    #include <stdio.h>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <cmath>
    #include<map>
    using namespace std;
    map<char,int>map_cnt;
    int main()
    {
        int max_cnt=0;
        for(int i=0;i<4;i++){
            string str;
            getline(cin,str);
            for(int i=0;i<str.size();i++){
                char ch=str[i];
                if(ch>='A'&&ch<='Z'){
                    map_cnt[ch]++;
                    max_cnt=max(max_cnt,map_cnt[ch]);
                }
            }
        }
        for(int i=max_cnt;i>0;i--){
            for(int j=0;j<26;j++){
                if(map_cnt['A'+j]==i){
                    cout<<"* ";
                    map_cnt['A'+j]--;
                }
                else cout<<"  ";
            }
            cout<<endl;
        }
        for(int i=0;i<26;i++){
            cout<<char('A'+i)<<" ";
        }
        cout<<endl;
    

    D - Word-Search Wonder##

    题意:###

    在字符矩阵中,找到某个字符串在矩阵中的起点和终点。(保证最多一个解)

    题解:###

    暴力,八个方向探索。

    代码:###

    #include <iostream>
    #include <string>
    #include <stdio.h>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <cmath>
    #include<map>
    using namespace std;
    const int N=105;
    char maze[N][N];
      int n;
    void output(int x1,int y1,int x2,int y2){
        cout<<x1+1<<','<<y1+1<<" "<<x2+1<<","<<y2+1<<endl;
    }
    void gao(string str){
        int len=str.size();
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(maze[i][j]==str[0]){
                    int n_i=i,n_j=j;
                    //down
                    while(n_i<n&&maze[n_i][j]==str[n_i-i])n_i++;
                    if(n_i-i==len){
                        n_i--;
                        output(i,j,n_i,j);
                        return;
                    }
                    //up
                    n_i=i,n_j=j;
                    while(n_i>=0&&maze[n_i][j]==str[i-n_i])n_i--;
                    if(i-n_i==len){
                        n_i++;
                        output(i,j,n_i,j);
                        return;
                    }
                    //r
                    n_i=i,n_j=j;
                    while(n_j<n&&maze[i][n_j]==str[n_j-j])
                        n_j++;
                    if(n_j-j==len){
                        n_j--;
                        output(i,j,i,n_j);
                        return;
                    }
                     //l
                     n_i=i,n_j=j;
                    while(n_j>=0&&maze[i][n_j]==str[j-n_j])n_j--;
                    if(j-n_j==len){
                        n_j++;
                        output(i,j,i,n_j);
                        return;
                    }
                    //x
                    n_i=i,n_j=j;
                    while(n_j<n&&n_i<n&&maze[n_i][n_j]==str[n_j-j])n_j++,n_i++;
                    if(n_j-j==len){
                        n_j--;n_i--;
                        output(i,j,n_i,n_j);
                        return;
                    }
                    n_i=i,n_j=j;
                    while(n_j>=0&&n_i>=0&&maze[n_i][n_j]==str[j-n_j])n_j--,n_i--;
                    if(j-n_j==len){
                        n_i++;n_j++;
                        output(i,j,n_i,n_j);
                        return;
                    }
                    n_i=i,n_j=j;
                    while(n_j>=0&&n_i<n&&maze[n_i][n_j]==str[j-n_j])
                        n_j--,n_i++;
                    if(j-n_j==len){
                        n_j++;n_i--;
                        output(i,j,n_i,n_j);
                        return;
                    }
                    n_i=i,n_j=j;
                    while(n_j<n&&n_i>=0&&maze[n_i][n_j]==str[n_j-j])n_j++,n_i--;
                    if(n_j-j==len){
                        n_i++;n_j--;
                        output(i,j,n_i,n_j);
                        return;
                    }
    
                }
            }
        }
        puts("Not found");
    }
    

    E - A Mini Locomotive##

    题意:###

    一共(n)车厢,每个车厢人数为(a_i),可以带走三段连续的车厢人数,求最多可以带走的人数。

    题解:###

    贪心不可取,DP,类似01背包问题。
    (dp[i][j])表示遍历到第(i)个人,总共使用了(j)次的最大答案数量。

    代码:###

    #include <iostream>
    #include <string>
    #include <stdio.h>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <cmath>
    #include<map>
    using namespace std;
    const int N=5e4+10;
    int a[N];
    int pre[N];
    int dp[N][4];
    int n,len;
    int main()
    {
        int T;
        cin>>T;
        while(T--){
            cin>>n;
            for(int i=0;i<n;i++)
                for(int j=0;j<3;j++)
                    dp[i][j]=0;
            for(int i=0;i<n;i++){
                cin>>a[i];
                if(i==0)pre[i]=a[i];
                else pre[i]=pre[i-1]+a[i];
            }
            cin>>len;
    
            for(int i=0;i<n;i++){
             for(int j=1;j<=3;j++){
                   if(i<len)
                    dp[i][j]=pre[i];
                    else
                   dp[i][j]=max(dp[i-1][j],dp[i-len][j-1]+pre[i]-pre[i-len]);
                   //cout<<dp[i][j]<<"  ";
                }
               // cout<<endl;
            }
            cout<<dp[n-1][3]<<endl;
    
        }
        return 0;
    }
    

    EFG#

    都不难,一个贪心;一个裸的最小生成树,这个题已经遇到了几次了;一个最小哈夫曼树的模拟。这三题都不写了。

    I#

    没找到题目来源。

  • 相关阅读:
    vue3.0配置代理proxy 解决跨域问题
    1/26 机器人未来待解决问题
    每日一诵
    2020/11/14 关于股票的价格
    2020/11/14 再思股票价值
    11/2 股票价值
    我们为什么会越来越笨
    关于追女朋友
    关于早睡早起
    vue学习心得
  • 原文地址:https://www.cnblogs.com/gzr2018/p/12465045.html
Copyright © 2020-2023  润新知