hgoi#20190508

博客包含四道算法题,分别是Bachgold Problem(将整数分解为最多质数和)、Parallelogram is Back(根据平行四边形三点求第四点位置)、Voting(团队发言禁言竞争)、Leaving Auction(拍卖会查询赢家及价格),给出各题解法思路及AC代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

T1-Bachgold Problem

给你一个整数n(2≤n≤100000),问最多能将其分解成多少质数的和。
在第一行输出最多的质数数量k,下一行输出k个整数,为这些质数。

解法

贪心,分解成2和3明显是最优的

ac代码

#include<bits/stdc++.h>
using namespace std;
int n;
int main()
{
    scanf("%d",&n),printf("%d\n",n/2);
    while(n>3)printf("%d ",2),n-=2;
    printf("%d\n",n);
    return 0;
}

T2-Parallelogram is Back

输入一个平行四边形的三个顶点,输出第四个点的可能位置数量和这些位置

解法

这就是简单数学推导了,初中的知识吧=-=
第四个点一定只有3种可能,都算出来就好了

ac代码

#include<bits/stdc++.h>
using namespace std;
int a[5],b[5],suma,sumb;
int main()
{
    for(int i=1;i<=3;i++)scanf("%d%d",&a[i],&b[i]),suma+=a[i],sumb+=b[i];
    puts("3");
    for(int i=1;i<=3;i++)printf("%d %d\n",suma-2*a[i],sumb-2*b[i]);
    return 0;
}

T3-Voting

给定一个字符串,字符串中字符为D或R,代表两个团队
从1开始,每个人都有发言的权利,发言时,可以禁言一个人,使那个人以后都不能发言
如果一圈发言完还有1个以上的人能发言,就从1重新开始,直到只有1个人能发言,那个人所在的团队获胜

解法

可以挂个链表,然后头尾连起来,可以一直扫,结束条件可以优化,当场上只有一个团队时结束
因为最优策略是将另一个团队后一个发言的人禁言,所以每次扫到一个人,看是否被禁言,如果被禁言了,在链表中删去这个点
这样做的复杂度是nlogn的,因为每次会禁言一半

ac代码

#include<bits/stdc++.h>
#pragma GCC optimize(2)
using namespace std;
int n,nw,s[200010],l[200010],r[200010],cnta,cntb,lena,lenb,dela,delb;
char ch;
int main()
{
    scanf("%d",&n),getchar();
    for(register int i=1;i<=n;++i)
    {
        scanf("%c",&ch),l[i]=i-1,r[i]=i+1;
        if(ch=='D')s[i]=1,cnta++;else s[i]=2,cntb++;
    }
    l[1]=n,r[n]=1,nw=1;
    while(cnta!=lena&&cntb!=lenb)
    {
        if(s[nw]==1)
        {
            if(dela)r[l[nw]]=r[nw],l[r[nw]]=l[nw],dela--;
            else delb++,lenb++;
        }
        if(s[nw]==2)
        {
            if(delb)r[l[nw]]=r[nw],l[r[nw]]=l[nw],delb--;
            else dela++,lena++;
        }
        nw=r[nw];
    }
    if(cnta==lena)puts("R");else puts("D");
    return 0;
}

T4-Leaving Auction

一场拍卖会,共n个买家。这些买家共出价n次,有的买家可能一次都没有出价。
每次出价用(ai,bi)表示,ai为此次出价人的编号,bi为价格。
出价严格递增(bi<bi+1)并且没有玩家在一轮竞拍中在没有其他竞争对手的情况下自动增加自己的出价(ai!=ai+1)。
现在给定q次查询,每次去掉一些出价者及其所有出价,问最后谁是赢家并且他以什么价格赢得拍卖品。

解法

首先第一小问,求谁是赢家,可以先排序,由于k的和限定在20w,所以每次从排名上扫来找到赢家
对于第二小问,求赢家出的价格,可以换一种思路,找到比第二名的最高出价高的第一个出价,就是答案
这个就很好维护了,找到第二名的复杂度也是k的和,然后二分找到比他大的第一个出价就可以了
总复杂度nlogn,tips:memset的复杂度是n(emmmm),所以不要在循环里加上memset,怎么死的都不知道

ac代码

#include<bits/stdc++.h>
using namespace std;
struct node{int num;}b[200010];
vector<int>a[200010];
int n,m,q,x,y,lim[200010],ll[200010];
int cmp(node xx,node yy){return a[xx.num][a[xx.num].size()-1]<a[yy.num][a[yy.num].size()-1];}
int find(int k)
{
    for(int i=k;i>=1;i--)if(!lim[b[i].num])return i;
    return 0;
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<=n;i++)a[i].push_back(0);
    for(int i=1;i<=n;i++)scanf("%d%d",&x,&y),a[x].push_back(y),b[i].num=i;
    sort(b+1,b+1+n,cmp),scanf("%d",&m);
    while(m--)
    {
        scanf("%d",&q);
        for(int i=1;i<=q;i++)scanf("%d",&ll[i]),lim[ll[i]]=1;
        x=find(n),lim[b[x].num]=1,y=find(x-1),lim[b[x].num]=0;
        if(!a[b[x].num][a[b[x].num].size()-1])puts("0 0");
        else printf("%d %d\n",b[x].num,*upper_bound(a[b[x].num].begin(),a[b[x].num].end(),a[b[y].num][a[b[y].num].size()-1]));
        for(int i=1;i<=q;i++)lim[ll[i]]=0;
    }
    return 0;
}
# P8482 「HGOI-1」Number ## 题目背景 $\text{bh1234666}$ 正在学习乘法! ## 题目描述 $\text{bh1234666}$ 有一定数量的数字 $0 \sim 9$,现在他想让你寻找一种分配方案,将它们分成两个整数,使得他们的乘积 $p$ 最大。 由于 $\text{bh1234666}$ 不喜欢太大的数,所以你只需要输出**两个非负整数**,使它们的乘积**等于**最大乘积 $p$,但是这两个整数 $0 \sim 9$ 的数量不能等于给定的数量(任意一个数字数量不相等即可,**不考虑前导零**)。 $\text{bh1234666}$ 是很善良的,如果 $0 \sim 9$ 的数量等于给定的数量了,你依旧可以得到的一半的分。 ## 输入格式 第一行十个整数 $c_0,c_1,\cdots c_9$,分别表示 $0 \sim 9$ 的个数。 ## 输出格式 共两行每行一个非负整数,分别表示你给出的两个非负整数。 ## 输入输出样例 #1 ### 输入 #1 ``` 1 2 3 2 1 1 2 1 2 1 ``` ### 输出 #1 ``` 13949030 620572547 ``` ## 说明/提示 #### 样例解释 最大可能乘积为 $97643210 \times 88653221=13949030 \times 620572547=8656385075279410$。 若输出 $97643210 \times 88653221$ 则只能得到一半的分,因为 $0\sim 9$ 出现的次数与给定的相同。 #### 数据范围及约定 本题采用**捆绑测试**,共有 $5$ 个 $\text{subtask}$,最终分数为所有 $\text{subtask}$ 分数之。 $$ \def\arraystretch{1.5} \begin{array}{|c|c|c|}\hline \textbf{Task} & \textbf{Score} & \sum c_i\le \cr\hline 1 & 10 & 20 \cr\hline 2 & 20 & 100 \cr\hline 3 & 20 & 5000 \cr\hline 4 & 20 & 10^6 \cr\hline 5 & 30 & 10^7 \cr\hline \end{array} $$ 对于 $100\%$ 的数据,保证 $1 \le c_i$,$\sum c_i \le 10^7$。 #### 说明 本题有 $\text{spj}$,两数乘积正确得一半的分,数量与给出的不同且乘积正确得全部分数。故每一 $\text{subtask}$ 的得分为其中所有数据点得分的**最小值**。
最新发布
07-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值