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

相关推荐
摇摆的含羞草16 分钟前
哈希(hash)算法使用特点及常见疑问解答
算法·哈希算法
农夫山泉2号29 分钟前
【c++】——c++编译的so中函数有额外的字符
java·服务器·c++
Fine姐42 分钟前
数据结构04——二叉树搜索树BST
数据结构
仰泳的熊猫1 小时前
1077 Kuchiguse
数据结构·c++·算法·pat考试
LYFlied1 小时前
【每日算法】LeetCode 19. 删除链表的倒数第 N 个结点
算法·leetcode·链表
阿里巴巴AI编程社区1 小时前
Qoder 提效实战:数据开发工程师用 Qoder 提效50%
数据结构
踏浪无痕1 小时前
计算机算钱为什么会算错?怎么解决?
后端·算法·面试
消失的旧时光-19431 小时前
从 C 链表到 Android Looper:MessageQueue 的底层原理一条线讲透
android·数据结构·链表
夏乌_Wx1 小时前
练题100天——DAY28:找消失的数字+分发饼干
数据结构·算法
lzh200409192 小时前
二叉搜索树与双向链表
数据结构·链表