HAUE 新生周赛(七)题解

赛后感慨

其实要我说榜单有点歪,虽然第一题代码量很短,但其实思考这个答案还是挺费劲的(如果提前没有了解过海盗分金这个模型的话),反观F、J和I纯暴力题解决量却很少(我明明把A题面搞得那么长你们都读下来了,为什么这三个不读呢....),还是说真是蒙的,其实D是做的压轴,没想到还有人能写出来,强大

A 贪心的小L

如果读明白题会发现,其实这里对每个人只有给或没给,你给了他就支持,不给就不支持,因为换下一个人可能就不给你了。

作为第一继承人,他肯定想让你去世,换他分配,你给不给都是一样的,你需要的是给半数人,让他们支持你就可以了,这题被简化了可能大部分人都是蒙的n/2,他底层类似

1 2 3 4 5 6 7

0 1 0 1 0 1 0 这样交替给,对于1给不给可能都要让你去世,而对于二,如果你去世,他变成1,那么新船长肯定也不给他,这样交替着给,如果1当上船长,原先分配1的都变成0这样即为最佳安排情况,所以最终是n/2(早知道让你们写出来分配情况了,你们也太敢蒙了...)

cpp 复制代码
void solve()
{
    int n;
    cin>>n;
    cout<<(n/2)<<endl;
}

B 猫猫爱喵喵

这题就是很简单的根据给出的时间做if判断即可,没什么大难度,按照题意写代码即可

cpp 复制代码
void solve()
{
    int a,b;
    char o;
    cin>>a>>o>>b;
    int sum=a-12;
    if(sum<0)
    {
        cout<<"不管猫猫的事哦~\n";
    }
    else
    {
        int ans=0;
        for(int i=0;i<sum;i++)
        {
            ans+=i+1;
        }
        ans+=min(sum+1,b);    
        cout<<ans<<endl;
    }

}

C 宝石

首先观察题目公式,下面的最小公倍数和最大公约数乘积明显就是a×b,化简出来其实就是

|a^2 − b^2|,所以我们让最小和最大的搭配即可

cpp 复制代码
void solve()
{
    int n;
    cin>>n;
    for(int i=0;i<n;i++)
    cin>>a[i];
    sort(a,a+n);
    int t;
    cin>>t;
    for(int i=0;i<t;i++)
    {
        cout<<a[n-i-1]*a[n-i-1]-a[i]*a[i]<<endl;
    }
    
}

D 看星星的小X

差分算法题,其实三个问题已经提示了大体思路(以时间做下标对一整天做差分即可),会差分的做出来应该问题不大,有问题自己再想想

cpp 复制代码
int to_seconds(const string &t) 
{
    int hh = stoi(t.substr(0,2));
    int mm = stoi(t.substr(3,2));
    int ss = stoi(t.substr(6,2));
    return hh * 3600 + mm * 60 + ss;
}
void solve()
{
    int n,a,b,c,d,e,f;
    cin>>n;
    string name,s,sstart,sfinish;
    int ma=0;
    while(n--)
    {
        cin >> s >> sstart >> sfinish; 
        int start = to_seconds(sstart);
        int finish = to_seconds(sfinish);
        diff[start]++,diff[finish+1]--;
        int sum=(finish-start+1);
        if(sum>ma)
        {
            name=s;
            ma=sum;
        }
        else if(sum==ma)
        {
            name=min(name,s);
        }
    }
    int ans=diff[0],single=0;
    if(diff[0]==1)
        single++;
    for(int i=1;i<60*60*24;i++)
    {
        diff[i]+=diff[i-1];
        if(diff[i]==1)
            single++;
        ans=max(ans,diff[i]);
    }
    cout<<name<<" "<<single<<" "<<ans;
}

E 你的名字?

要求可随意组合为目标串,只需要看他们含有的字符串一致不一致即可,方法很多,我这里直接排序看相同也是做法之一,也可以做桶之类的,解法很多

cpp 复制代码
void solve()
{
    int n;
    string s1,s2;
    cin>>n>>s1>>s2;
    sort(s1.begin(),s1.end());
    sort(s2.begin(),s2.end());
    if(s1==s2)
    cout<<"YES"<<endl;
    else
    cout<<"NO"<<endl;
}

F 善良的小X

题目数据很小啊,没打算考太难,按照题目意思直接O(n^2)枚举即可,最后输出最大值(为什么大家伙不写呢.....)

cpp 复制代码
void solve()
{
    int n,x;
    cin>>n;
    double ans=INT_MAX;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
    }
    cin>>x;
    for(int i=0;i<n;i++)
    {
        int cnt=0,sum=0;
        for(int j=i;j<n;j++)
        {
            sum+=a[j];
            cnt++;
            if(cnt>=8)
            {
                double temp=sum*1.0/cnt;
                if(temp-x>1e-5&&ans-temp>1e-5)
                {
                    ans=temp;
                }
            }
        }
    }
    if(ans==INT_MAX)
    cout<<-1;
    else
    cout<<fixed<<setprecision(2)<<ans;
}

G 面向结果编程

很有意思的一道题,题目也提示了做法(预处理),这里用init函数先求出来对应正整数的对应质数数量,然后对于每一次样例不用再重复的求值,也就是原先需要处理t(样例数)次,其实只需要处理一次存下来即可,按照题意输出即可,可以学一下R这个格式输出(非常好用)

cpp 复制代码
int pre[100005];
bool su(int x)
{
    int e=sqrt(x);
    for(int i=2;i<=e;i++)
    {
        if(x%i==0)
        return 0;
    }
    return 1;
}
void init()
{
    pre[1]=0;
    for(int i=2;i<=1e5;i++)
    {
        pre[i]=pre[i-1]+su(i);
    }
}
void solve()
{
    int x;
    cin>>x;
    cout<<R"(#include<stdio.h>

int main() {
    int n;
    scanf("%d", &n);
    if (n == 1) printf("0");)"<<endl;
    for(int i=2;i<=x;i++)
    {
        cout<<"    else if (n == "<<i<<") printf(\""<<pre[i]<<"\");"<<endl;
    }
    cout<<R"(    return 0;
})"<<endl;
}

H 调用函数

首先观察题目其实也就发现对于每一个操作只有加减,所以对应的操作数其实不太重要,我们统计出来所有的加减,最后加上原来的数即可

cpp 复制代码
signed main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        string s;
        cin>>n>>s;
        int ans=0;
        string p="";
        for(int i=0;i<n;i++)
        {
            if(s[i]=='A')
                ans+=11451400;
            else if(s[i]=='B')
                ans+=31415900;
            else if(s[i]=='C')
                ans-=27182800;
            else if(s[i]=='D')
                ans-=1638400;
            else if(s[i]>='0'&&s[i]<='9'||s[i]=='-')
                p+=s[i];
        }
        int k=stoll(p);
        cout<<ans+k<<endl;
    }
}

I day4-别让企鹅吃石头

数据范围同样不大,按照题意每次枚举每一个位置移动的概率(左,中,右)这样,最后统计最大输出即可

cpp 复制代码
int main() {
    int N, k;
    double p, q;
    cin >> N >> p >> q >> k;
    int n = N * 2 + 1;
    vector<double> a(n,0.0);
    a[N] = 1.0;
    for(int i = 0; i < k; ++i){
        vector<double> dp(n, 0.0);
        for (int j = 0; j < n; ++j) {
            if (a[j] == 0) continue;
            int pos = j - N;
            if (pos == -N) {
                dp[j] += a[j] * (1 - q);
                dp[j + 1] += a[j] * q;
            }
            else if (pos == N) {
                dp[j] += a[j] * (1 - p);
                dp[j - 1] += a[j] * p;
            }
            else {
                dp[j - 1] += a[j] * p;
                dp[j + 1] += a[j] * q;
                dp[j] += a[j] * (1 - p - q);
            }
        }
        a = dp;
    }
    vector<int> t;
    double ans = 0.0;
    for (int i = 0; i < n; ++i) {
        if (a[i] > ans) {
            ans = a[i];
            t.clear();
            t.emplace_back(i - N);
        }
        else if (a[i] == ans) {
            t.emplace_back(i - N);
        }
    }
    for (auto& v : t) {
        cout << v << " ";
    }
    printf("\n%.5lf", ans);

    return 0;
}

J 善用魔法的小L

数据范围依旧很小,支持O(n^2),从每一个题的位置做反转,统计得分,依次枚举即可(代码写的长是后面写着写着乱了,其实还是挺简单的,提供思路,不要学我.....)

cpp 复制代码
int a[1005][10];
int b[1005][10];
int c[10];
int con(int a[],int b[])
{
    int cnt=0;
    for(int i=0;i<4;i++)
    {
        cnt+=b[i];
    }
    if(!cnt)
    return 0;
    for(int i=0;i<4;i++)
    {
        c[i]=a[i]+b[i];
    }
    for(int i=0;i<4;i++)
    {
        if(c[i]==-1)
        return 0;
    }  
    for(int i=0;i<4;i++)
    {
        if(c[i]==1)
        return 3;
    }
    return 6;
}
void solve()
{
    int n;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<4;j++)
        {
            cin>>a[i][j];
        }
    }
        for(int i=0;i<n;i++)
    {
        for(int j=0;j<4;j++)
        {
            cin>>b[i][j];
            b[i][j]*=-1;
        }
    }
    int ans=0;
    for(int i=0;i<n;i++)
    {
        int temp=0;
        for(int j=0;j<n;j++)
        {
            temp+=con(a[(i+j)%n],b[j]);   
        }
        ans=max(ans,temp);
    }
    cout<<ans;
}

总结

不管怎么样,HAUE新生周赛到此结束,中间也有些乱子,不过最后还算是顺利结束。长达七周的比赛,能促进学习不少知识,也能让大家的大学生活多一些共同话题,建立一些羁绊,成长不少。一次的比赛结束不是完结,后续还有n次更难,更有含金量的比赛,继续加油。

相关推荐
q***64972 小时前
SpringMVC 请求参数接收
前端·javascript·算法
Lwcah2 小时前
Python | LGBM+SHAP可解释性分析回归预测及可视化算法
python·算法·回归
小此方2 小时前
从零开始手搓堆:核心操作实现 + 堆排序 + TopK 算法+ 向上调整 vs 向下调整建堆的时间复杂度严密证明!
开发语言·数据结构·算法
_OP_CHEN2 小时前
从零开始的Qt开发指南:(五)Qt 常用控件之 QWidget(上):解锁 Qt 界面开发的核心基石
开发语言·c++·qt·前端开发·qwidget·gui开发·qt常用控件
sulikey3 小时前
深入讲解:什么是 RAII(资源获取即初始化)——原理、实现、面试常考点与实战示例
c++·面试·智能指针·raii·shared_ptr·auto_ptr·资源获取即初始化
艾莉丝努力练剑3 小时前
【Git:多人协作】Git多人协作实战:从同分支到多分支工作流
服务器·c++·人工智能·git·gitee·centos·项目管理
前端炒粉5 小时前
35.LRU 缓存
开发语言·javascript·数据结构·算法·缓存·js
断剑zou天涯7 小时前
【算法笔记】窗口内最大值或最小值的更新结构
java·笔记·算法
smj2302_796826527 小时前
解决leetcode第3753题范围内总波动值II
python·算法·leetcode