第三次双周赛

7-4 神秘密码

分数 20

全屏浏览题目切换布局

作者 neuqAcmClub

单位 东北大学秦皇岛分校

传说二战时X国收到了上帝的一串密码,只有解开密码,才能阻止战争的继续进行,世界才会恢复和平。解开密码的第一道工序就是解压缩密码,上帝对于连续的若干个相同的子串"X"会压缩为"[DX]“的形式(D是一个整数且1<=D<=99),比如说字符串"CBCBCBCB"就压缩为”[4CB]“或者”[2[2CB]]“,类似于后面这种压缩之后再压缩的称为二重压缩。如果是”[2[2[2CB]]]"则是三重的。现在我们给你上帝发送的密码,请你对其进行解压缩。

输入格式:

一个字符串。

输出格式:

一个字符串。

输入样例:

在这里给出一组输入。例如:

AC[3FUN]

输出样例:

在这里给出相应的输出。例如:

ACFUNFUNFUN

【数据范围】

解压后的字符串长度在 20000 以内,最多只有十重压缩。保证只包含数字、大写字母、[]

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

思路

这道题主要考察递归的使用,这里的使用比较巧妙.我们写一个函数,每次都读入一个字符:

如果遇到’['就读取后面的数字,然后调用自身.

如果遇到’['就返回ret字符串;

否则把当前的字符加到目前的ret字符串中.

最后返回ret字符串

这里就乱在这个ret字符串放在代码的位置和什么时候返回

总结一下,就是要先把dg函数的功能想好(比如功能,返回值),然后正着写,根据提前准备好的递归返回值进行实现,最后就是补充细节.

代码实现

#include<bits/stdc++.h>
using namespace std;
string read()
{
    string ret="",s="";
    char c;
    int n;
    while(cin>>c)
    {
        if(c=='[')
        {
            cin>>n;
            s=read();
            while(n--)ret+=s;
        }
        else 
        {
            if(c==']')return ret;
            else ret+=c;
        }
    }
    return ret;
}
int main()
{
    cout<<read()<<endl;
    return 0;
}


7-5 h0114.国王游戏

分数 20

全屏浏览题目切换布局

作者 黄正鹏

单位 贵州工程应用技术学院

恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏。
首先,他让每个大臣在左、右手上面分别写下一个整数,国王自己也在左、右手上各写一个整数。
然后,让这 n 位大臣排成一排,国王站在队伍的最前面。
排好队后,所有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:
排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。
国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序,使得获得奖赏最多的大臣,所获奖赏尽可能的少。
注意,国王的位置始终在队伍的最前面。

输入格式:

第一行包含一个整数 n(1≤n≤1000),表示大臣的人数。
第二行包含两个整数 a (0<a)和 b(b<10000),之间用一个空格隔开,分别表示国王左手和右手上的整数。
接下来 n 行,每行包含两个整数 a 和 b,之间用一个空格隔开,分别表示每个大臣左手和右手上的整数。

输出格式:

输出只有一行,包含一个整数,表示重新排列后的队伍中获奖赏最多的大臣所获得的金币数。

输入样例:

在这里给出一组输入。例如:

3
1 1
2 3
7 4
4 6

输出样例:

在这里给出相应的输出。例如:

2

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

思路

这道题考查两个知识点,一个是贪心的应用,一个是高精度

贪心的做法:直接将所有大臣按左右手上的数的乘积从小到大排序,得到的序列就是最优排队方案。

贪心的证明相对较麻烦,考试的时候最好在一定的理论基础上,直接猜结论,下面附上证明方法:

请添加图片描述

对于这道题的高精度,反倒是把我考倒的点~~(虽然写过原题)~~

这题要写高精度的乘法和除法,刚开始怎么写,有三个点都是超时,被卡常……后来在玄神的指导下,改出了ac代码,太感谢了(拜谢.jpg)

主要是有两个知识点要注意

1、to_string()函数用手写会快一点点

2、在字符串加减的时候,加到前面是O(n),加到后面是O(1),而且写的时候要写成s+=a的形式

3、在写高精度的时候,最好用int来存储,避免string的拷贝构造消耗时间

ret+=(char)((z[i])+'0');

在改之前,最坏的情况要0.48秒左右

改之后在0.1秒左右,完美ac!

代码实现

#include<bits/stdc++.h>
const int maxn=1e3+5;
using namespace std;
short x[4001]={};
short y[4001]={};


string to_s_ret="";
int inter[10];
string to_s(int n) //手写to_string()函数
{
    to_s_ret="";
    int xb=0;
    if(n==0 )return "0";
    while(n>0) 
    {
        inter[xb++]=n%10;
        n/=10;
    }
    for(int i=xb-1;i>=0;i--)
    {
        to_s_ret+=(char)(inter[i]+'0');
    }
    return to_s_ret;
}


string Max(string a,string b)//自定义字符串大小比较函数
{
    if(a=="")return b;
    if(a.size()>b.size())return a;
    else if(a.size()<b.size()) return b;
    else 
    {
        return max(a,b);
    }
}
struct per//定义人这个类
{
    int a,b;
    int total;
    bool operator<(per p) const 
    {
        return this->total<p.total|| this->total==p.total && this->b>p.b;
    }
}Per[maxn];

string multi(string s1,string s2)//高精度乘法
{
    int l1=s1.size();
    int l2=s2.size();
    short z[4001]={};
    string ret="";
    for(int i=1;i<=l1;i++) x[i]=s1[l1-i]-48;
    for(int i=1;i<=l2;i++) y[i]=s2[l2-i]-48;
    for(int i=1;i<=l1;i++) 
    {
        for(int j=1;j<=l2;j++)
        {
            z[i+j]+=(z[i+j-1]+x[i]*y[j])/10;
            z[i+j-1]=(z[i+j-1]+x[i]*y[j])%10;
        }
    }
    int now=l1+l2;
    while(z[now]==0 && now>1) now--;
    for(int i=now;i>=1;i--)
    {
        ret+=(char)((z[i])+'0');
    }
    return ret;
}
short z[4001]={};
string div(string s,int b)//高精度除法
{
    int l=s.size();
    int t=0;
    
    string ret="";
    for(int i=1;i<=l;i++)
    {
        x[i]=s[i-1]-48;
    }
    for(int i=1;i<=l;i++)
    {
        z[i]=(t*10 + x[i])/b;
        t=(t*10 +x[i])%b;
    }
    int now=1;
    while(z[now]==0 && now<l) now++;
    for(int i=now;i<=l;i++)
    {
        ret+=(char)((z[i])+'0');
    }
    return ret;
    
}
int main()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(0);


  // clock_t tStart, tFinish;
	// float tElapseTime;
	// tStart = clock();
  //  freopen("shuju.in","r",stdin);
    int n;
    cin>>n;
    cin>>Per[0].a>>Per[0].b;
    for(int i=1;i<=n;i++)
    {
        cin>>Per[i].a>>Per[i].b;
        Per[i].total=Per[i].a*Per[i].b;
    }
    sort(Per+1,Per+n+1);
    string ret="1";
    string ans="";
    for(int i=1;i<=n;i++)
    {
        ret=multi(ret,to_s(Per[i-1].a));
        ans=Max(ans,div(ret,Per[i].b));
    }
    cout<<ans<<endl;
  
    // tFinish = clock();
 
	// tElapseTime = (float)(tFinish-tStart)/CLOCKS_PER_SEC;
 
	// cout<<"消耗的时间,秒数为: "<<tElapseTime<<endl;
    return 0;
}

总结

  1. 从这次比赛中可以知道自己对递归的掌握还要加强.
  2. 高精度的string在用的时候,要注意字符串相加的原则s+=a
  3. 写过的原题都没写出来,说明最近对题目的整理还是有点欠缺,要注意整理和复习
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值