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次更难,更有含金量的比赛,继续加油。

相关推荐
执着2599 小时前
力扣hot100 - 101、对称二叉树
数据结构·算法·leetcode
多恩Stone9 小时前
【3D-AICG 系列-1】Trellis v1 和 Trellis v2 的区别和改进
人工智能·pytorch·python·算法·3d·aigc
三月微暖寻春笋9 小时前
【和春笋一起学C++】(五十九)派生类和基类之间的关系
c++·基类·派生类·关系
数智工坊9 小时前
【数据结构-栈、队列、数组】3.3栈在括号匹配-表达式求值上
java·开发语言·数据结构
mit6.8249 小时前
模运算|z函数 字符串匹配
算法
阿豪只会阿巴9 小时前
【吃饭香系列】二周目|代码随想录算法训练营第七天|454.四数相加II |383. 赎金信 |15. 三数之和 |18. 四数之和
算法
小O的算法实验室9 小时前
2025年COR SCI2区,考虑风场影响的无人机搜救覆盖路径规划精确界算法,深度解析+性能实测
算法·无人机·论文复现·智能算法·智能算法改进
xqqxqxxq9 小时前
洛谷算法1-3 暴力枚举(NOIP经典真题解析)java(持续更新)
java·开发语言·算法
_OP_CHEN9 小时前
【算法基础篇】(五十五)卡特兰数封神之路:从括号匹配到二叉树构造,组合数学的万能钥匙!
算法·蓝桥杯·c/c++·组合数学·卡特兰数·算法竞赛·acm/icpc
阿猿收手吧!9 小时前
【C++】inline变量:全局共享新利器
开发语言·c++