第二屆“傳智杯”全國大學生IT技能大賽(初賽同步)


P6363 軟件工程實習

題目描述

某大學的《軟件工程》必修課分為理論和實踐部分。理論部分由該校教授完成授課;而實踐部分是由第三方的公司主導,需要同學們在五周時間內自學 HTML、css、JavaScript、vue、Python、django 等技術,並組隊完成一個真實的互聯網商業應用。

參與這個課程的有 \(n(0\le n \le 1000)\) 個學生,分成了不超過 \(26\) 個隊伍,每個隊伍用 \(A\)\(Z\) 來表示。每個隊伍都會完成一個項目,並以隊伍為單位,給所有隊伍(包括自己隊伍)打分,范圍是 \(0\)\(100\) 的整數。

為了平息學生對這門課產生的出多問題的不滿(比如工作量太大、時間過於緊張、考核方式不公平等),老師決定使用一種“看起來”很公平的方式來決定每組隊伍的項目得分:

對於某個隊伍,首先計算所有隊伍(包括自己)給這個隊伍評分的平均值,然后剔除掉和這個平均值差別超過 \(15\) 分的評分(保證不會出現所有的評分全部被剔除的情況),最后再對剩余的評分求平均值,四舍五入取整后作為這個隊伍的項目得分。

對於每一個同學,我們已經得知他們的隊伍代號和理論成績(也是 \(0\)\(100\) 分的整數)。這位同學的最后得分就是 \(60\%\) 的理論成績加上 \(40\%\) 的所在隊伍的項目得分,然后四舍五入取整。

現在老師想知道所有同學的分數排行。請按最后得分從高到低的順序,輸出每位同學的得分和他所在的隊伍。

輸入格式

第一行兩個整數 \(n\)\(k\),分別表示學生數和隊伍數。

接下來 \(n\) 行,每行一個整數 \(s_i\) 和一個大寫字母 \(c_i\) ,表示第 \(i\) 個選手的理論分數和隊伍編號。保證隊伍編號范圍是從 \(A\) 開始后連續 \(k\) 個字母中的一個。

接下來 \(k\) 行,每行 \(k\) 個整數。其中第 \(i\) 行第 \(j\) 列的整數 $a_{i,j} 表示第 \(i\) 個隊伍給第 \(j\) 個隊伍的評分,當 \(i=j\) 時,就是自評。

輸出格式

輸出 \(n\) 行表示答案,得分高的同學優先輸出,得分相同時隊伍編號較小的同學優先輸出。對於每一行,先輸出這位同學成績,然后輸出代表他的隊伍編號的大寫英文字母。

輸入

6 3
70 A
80 A
65 B
95 B
85 C
90 C
70 90 100
95 88 85
30 47 100

輸出

93 B
92 C
89 C
76 A
75 B
70 A

說明/提示

\(A\) 組收到的分數分別是 \(70,95,30\),其平均分為 \(65\),則 \(95,30\) 被作為無效成績剔除,因此 \(A\) 組的項目得分是 \(70\) 分。
\(B\) 組收到的分數分別是 \(90,88,47\),其平均分為 \(75\),則 \(47\) 被作為無效成績剔除,因此 \(B\) 組的項目得分是 \(89\) 分。
\(C\) 組收到的分數分別是 \(100,85,100\),其平均分為 \(95\),沒有打分被剔除,因此 \(C\) 組的項目得分是 \(95\) 分。

解題思路

模擬

模擬題,注意四舍五入~

  • 時間復雜度:\(O(nlogn+k^2)\)

代碼

#include<bits/stdc++.h>
#define fi first
#define se second
using namespace std;
int n,k,score[30][30],final_score[30],sum[30];
pair<int,int> res[1005],can[1005];
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
    {
        int s;
        char c;
        scanf("%d %c",&s,&c);
        can[i]={s,c-'A'+1};
    }
    for(int j=1;j<=k;j++)
        for(int i=1;i<=k;i++)
        {
            scanf("%d",&score[i][j]);
            sum[i]+=score[i][j];
            final_score[i]=sum[i];
        }
    for(int i=1;i<=k;i++)
    {
        int cnt=k;
        for(int j=1;j<=k;j++)
            if(abs(sum[i]-k*score[i][j])>k*15)final_score[i]-=score[i][j],cnt--;
        final_score[i]=int(1.*final_score[i]/cnt+0.5);
    }
    for(int i=1;i<=n;i++)
        res[i]={int(0.6*can[i].fi+0.4*final_score[can[i].se]+0.5),can[i].se};
    sort(res+1,res+1+n,[](auto &a,auto &b){if(a.fi!=b.fi)return a.fi>b.fi;return a.se<b.se;});
    for(int i=1;i<=n;i++)
        printf("%d %c\n",res[i].fi,res[i].se-1+'A');
    return 0;
}

P6364 1024 程序員節發橙子

題目描述

每年的 1024 程序員節日,黑馬程序員都會舉辦大型的慶祝活動。今年的程序員節也不例外,每個班級的同學都發了橙子。

班級里有 \(n\) 名同學從前到后排成一排,且已經得知了這些同學的成績,其中第 \(i\) 名同學的成績是 \(a_i\)。班主任想根據同學們上個階段的考試成績來評定發橙子的數量。為了激勵成績優秀同學,發橙子時需要滿足如下要求:

  • 相鄰同學中成績好的同學的橙子必須更多。若相鄰的同學成績一樣,則它們分到的數量必須平等。
  • 每個同學至少分配一個橙子
    由於預算有限,班主任希望在符合要求的情況下發出盡可能少的橙子。請問,至少需要准備多少橙子呢?

輸入格式

第一行是一個整數 \(n\),表示學生數量。

接下來一行有 \(n\) 個整數,第 \(i\) 個整數 \(a_i\),表示第 \(i\) 個同學的成績。

輸出格式

輸出答案,也就是需要最少准備多少個橙子。

輸入

5
3 4 5 4 3

輸出

9

說明/提示

樣例 1 解釋
每位同學拿到的橙子的數量分別是 \(1,2,3,2,1\),所以至少需要准備 \(9\) 個。

數據規模與約定

對於全部的測試點,保證 \(1 \leq n \leq 10^6\)\(0 \leq a_i \leq 10^9\)

解題思路

記憶化搜索

同題:135. 分發糖果
注意:結果會爆int

  • 時間復雜度:\(O(n)\)

代碼

#include<bits/stdc++.h>
using namespace std;
int f[1000005],a[1000005],n;
int dfs(int x)
{
    if(f[x]!=-1)return f[x];
    f[x]=1;
    if(x+1<=n&&a[x]>a[x+1])f[x]=max(f[x],dfs(x+1)+1);
    if(x-1>=1&&a[x]>a[x-1])f[x]=max(f[x],dfs(x-1)+1);
    return f[x];
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    memset(f,-1,sizeof f);
    long long res=0;
    for(int i=1;i<=n;i++)res+=dfs(i);
    printf("%lld",res);
    return 0;
}

P6365 眾數出現的次數

題目描述

傳智專修學員的課堂上,為了活躍氣氛,並鞏固位運算的知識,同學們玩起了一個游戲。

班級里有 \(n(n\le10^6)\) 名同學,每位同學都獲得了兩張卡,紅卡或者黑卡。每張卡上都有一個不超過 \(10^9\) 的非負整數。第 \(i\) 位同學手里紅卡數字是 \(a_i\) ,黑卡數字是 \(b_i\)

現在需要每位同學出牌。每位同學可以直接將紅卡上的數字打出,或者將自己的紅卡上的數字和自己黑卡數字進行按位異或操作后的結果打出。最后老師會收集所有同學打出的數字。

這些數字中出現次數最多的數字是眾數。在所有同學合作的最優策略下,我們希望眾數對應數字出現的次數盡可能多。請問出現次數最多的數字是多少呢?

輸入格式

第一行,一個正整數 \(n\)

接下來 \(n\) 行,其中第 \(i\) 行時非負整數 \(a_i,b_i\) 代表第 ii 名同學手上紅卡和黑卡的數字。

輸出格式

一個整數,表示答案。如果有多個解,請輸出最小的那個。

輸入

4
21 9
28 9
28 3
17 4

輸出

21

說明/提示

樣例解釋:

眾數出現次數最多是 \(3\) 次,有如下兩種方法:

\(1\) 號同學直接出紅卡,\(2\) 號同學出紅黑異或,\(3\) 號同學隨便出,\(4\) 號同學出紅黑異或。這樣 \(1,2,4\) 號同學都可以打出 \(21\)
\(1\) 號同學出紅黑異或,\(2\) 號同學直接出紅卡,\(3\) 號同學直接出紅卡,\(4\) 號同學隨便出。這樣 \(1,2,3\) 號同學都可以打出 \(28\)
所以 \(21\)\(28\) 都是出現次數最多的眾數,因為最多可以出現 \(3\) 次,不存在出現 \(4\) 次的方案。但是由於要求如果有多解輸出小的,請輸出 \(21\)

解題思路

hash

設置一個哈希表:hash:[x,y],表示xhash中出現了y次,這y次是由不同同學貢獻的,如果一個同學給的兩個值相同,則對該值只貢獻一次,要求的就是滿足最大的y的同時最小的x

  • 時間復雜度:\(O(n)\)

代碼

#include<bits/stdc++.h>
using namespace std;
unordered_map<int,int> mp;
int n,x,y;
int main()
{
    scanf("%d",&n);
    while(n--)
    {
        scanf("%d%d",&x,&y);
        mp[x]++;
        if(y)
            mp[x^y]++;
    }
    int mx=0,res=0;
    for(auto [x,y]:mp)
        if(mx<y)mx=y,res=x;
        else if(mx==y&&res>x)res=x;
    printf("%d",res);
    return 0;
}

P6366 特殊的翻轉

題目描述

k 老師在研究一段病毒程序的代碼。這段代碼是由一段長度不超過 \(10^6\) 的十六進制字符(也就是 09AF)組成的信息。現在 k 老師要將其轉換為二進制的 0/1 串(這個時候需要確保最高位是 1)。然后對這個 0/1 串進行“翻轉”操作。

對於每次“翻轉”操作,k 老師可以選擇這個 0/1 串中的其中一位,將這一位和這一位相鄰的兩位,一共三位,分別進行“翻轉”(也就是 0 變 1,1 變 0)。如果指定的這一位是序列的開頭或者結尾,那么翻轉這一位和存在的相鄰位即可。

k 老師想知道,如何用最少的“翻轉”步驟,將這個 0/1 串變為全 0 的串。

輸入格式

一個十六進制的字符串,由 09AF 構成。

輸出格式

最少能將其變為全 0 串需要的“翻轉”步驟次數。如果無論如何都不能將其變為全 0 串,則輸出 No

輸入 #1

15

輸出 #1

3

輸入 #2

FF

輸出 #2

3

輸入 #3

10

輸出 #3

No

說明/提示

樣例解釋:

十六進制的 15 對應二進制的 10101,翻轉第 1/3/5 位,就可以全部變為 0。

十六進制的 FF 對應二進制的 11111111,翻轉第 2/5/8 位,就可以全部變為 0。

十六進制的 10 對應二進制的 10000,無法全變為 0。

解題思路

枚舉+貪心

首先,可以確定一點:同一個位置最多翻轉一次,這是因為翻轉兩次等於沒有翻轉。從下標為 \(0\) 的位置開始,如果該位置為 \(1\),則有兩種選擇:翻轉該位置或與其相鄰的位置。且前面已經翻轉好的,后面不應該對其有影響,依次遞推即可;如果該位置為 \(0\),不考慮該位置。

  • 時間復雜度:\(O(n)\)

代碼

#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
string he,bi;
string get(int x)
{
    string t;
    do
    {
        t+=to_string(x%2);
        x/=2;
    }while(x);
    while(t.size()<4)t+='0';
    reverse(t.begin(),t.end());
    return t;
}
int op(int pos)
{
    int res=0,n=bi.size();
    if(bi.front()=='1')
    {
        res++;
        if(pos==0)bi[1]=char(bi[1]^1),pos++;
        else
        {
            bi[1]=char(bi[1]^1);
            bi[2]=char(bi[2]^1);
        }
    }
    for(int i=pos;i<n;i++)
    {
        if(bi[i]=='1')
        {
            if(i+1<n)
            {
                res++;
                bi[i+1]=char(bi[i+1]^1);
                if(i+2<n)bi[i+2]=char(bi[i+2]^1);
            }
        }
    }
    if(bi.back()=='1')return inf;
    return res;
}
int main()
{
    cin>>he;
    for(char &c:he)
    {
        if(c>='0'&&c<='9')bi+=get(c-'0');
        else
            bi+=get(c-'A'+10);
    }
    while(bi.size()>1&&bi.front()=='0')bi.erase(bi.begin());
    if(bi.size()==1)
    {
        if(bi[0]=='0')cout<<0;
        else
            cout<<1;
    }
    else if(bi.size()==2)
    {
        if(bi=="11")
            cout<<1;
        else
            puts("No");
    }
    else
    {
        if(bi.front()=='1')
        {
            string t=bi;
            int res1=op(0);
            bi=t;
            int res2=op(1);
            if(res1==inf&&res2==inf)puts("No");
            else
                cout<<min(res1,res2);
        }
        else
        {
            int res=op(1);
            if(res==inf)puts("No");
            else
                cout<<res;
        }
    }
    return 0;
}


免責聲明!

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



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