牛客OI周赛10——提高组

A题——风雨无阻
题目描述
许cosin的宝贝手表被他的仇人gen海偷走了。他决定秘密前往gen海家,去找回他的手表。
许cosin历经千辛万苦,耗时3天,终于找到了gen海家。他通过观察发现gen海不在家,于是他决定偷偷潜入gen海家,然后找回手表。但他在gen海家的门前发现了一个密码锁,他必须解开这个锁才能进入gen海家。可是许cosin实在是太silly了,于是他就向你请教。请快速解决这个问题,gen海还有1秒就会回家了。
锁上有两行,第一行一个数字N。第二行是一串字符串S(|S|≤6105),字符串由许多子串构成,每个子串的格式均是XA
其中X是一个运算符,A是一个数字。X可能是
,+,-,
%
%,表示次方)。
现在需要把数字N代入字符串S,从左到右进行运算。密码就是运算结果的绝对值。

题目保证运算过程中N在
int
int(-2147483648~2147483647)范围内,^后面的数字只能为2。运算过程从左至右,不满足运算的优先级(详见样例)
输入描述:
两行,第一行一个正整数N
第二行是一个字符串S
输出描述:
一个数,表示运算结果的绝对值
示例:
5
-7*3
输出
6

ps:这题有点坑,明明说了在int范围内的,结果最后有一个样例没过,后来改成long long才过的,后面看了大佬们尖端的代码,感觉自己就是个zz,mmp
orz

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
char a[600005],b[1000];

int chack(char a){
	if(a=='*')return 1;
	if(a=='+')return 2;
	if(a=='-')return 3;
	return 4;
}
int main(){
	ll n,p=0;
	cin>>n;
	cin>>a;
	ll len1=strlen(a);
	for(ll i=0;i<len1;i++){
		if(a[i]<'0'||a[i]>'9'){
			if(a[i]=='^'){
				n*=n;
				i++;continue;
			}
			else{
				ll w=chack(a[i]);
				ll sum=0,k=0,g;
				for(ll j=i+1;a[j]>='0'&&a[j]<='9';j++){
					b[k++]=a[j];
				}
				g=k;
				for(ll j=0;j<k;j++){
					g--;
					sum+=(b[j]-'0')*pow(10,g);
				}
				if(w==1)n*=sum;
				if(w==2)n+=sum;
				if(w==3)n-=sum;
				if(w==4)n%=sum;
				i+=k;
			}
		}
	}
	cout<<abs(n)<<endl;
	return 0;
}

大佬代码:

#include<bits/stdc++.h>
using namespace std;
long long m,n;
char c;
int main(){
    scanf("%lld",&n);
    while(~scanf(" %c%lld",&c,&m)){
        if(c=='+')n+=m;
        else if(c=='-')n-=m;
        else if(c=='*')n*=m;
        else if(c=='%')n%=m;
        else if(c=='^')n*=n;
        else break;
    }
    if(n<0)n=-n;
    printf("%lld\n",n);
    return 0;
}

B题——Taeyeon的困惑
题目描述
今天,YPC正在热舞之中,嘴里唱着BJLY的神曲,沉浸在了自己的世界里。 然而Taeyeon又突然抽了一下,问YPC一个问题: 在一个长度为n的区间中,子区间[1,m],[2,m+1],[3,m+2],…,[n-m+1,n]中每个区间前K小之和的和是多少。

其中一个区间的前k小之和指的是将这个区间内的所有数从小到大排序后求出最前面的k个数之和
由于YPC热舞的起劲,无法自拔,于是这个问题只能你来回答。
输入描述:
第一行三个整数:n,m,K,意思如题 第二行n个正整数:a[i],意思如题
输出描述:
输出仅一行,每个区间前K大的数之和的和。

样例1:
输入
6 3 2
2 3 1 4 5 6
输出
21

说明:链接:https://ac.nowcoder.com/acm/contest/900/B
来源:牛客网

对于30%数据:1≤n,m≤1000,0≤k≤m≤n,0≤a[i]≤105,m接近于n/2
对于100%数据:1≤n,m≤105,0≤k≤m≤n,0≤a[i]≤105,m接近于n/2。
保证数据纯随机

ps:我本来想暴力骗点分的,结果一分没得,话说,正解是两个set来维护,反正我不会,弱爆了
符大佬代码:

#include<cstdio>
using namespace std;
const int MAXN=100005;
typedef long long LL;
int n,m,K,Now,Num,a[MAXN],hsh[MAXN];LL Ans,Sum;
#include<cctype>
int read(){
    int ret=0;char ch=getchar();bool f=1;
    for(;!isdigit(ch);ch=getchar()) f^=!(ch^'-');
    for(; isdigit(ch);ch=getchar()) ret=(ret<<1)+(ret<<3)+ch-48;
    return f?ret:-ret;
}
int main(){
    n=read(),m=read(),K=read();
    for(int i=1;i<=n;i++) a[i]=read();
    for(int i=1;i<m;i++) hsh[a[i]]++;hsh[a[0]]++;Now=0,Num=hsh[a[0]];
    for(int i=m;i<=n;i++){
        hsh[a[i-m]]--,hsh[a[i]]++;
        Num+=(a[i-m]>Now?0:-1)+(a[i]>Now?0:1);
        if(a[i-m]<=Now) Sum-=a[i-m];
        if(a[i]<=Now) Sum+=a[i];
        while(Num-hsh[Now]>K) Num-=hsh[Now],Sum-=(LL)hsh[Now]*Now,Now--;
        while(Num<K) Num+=hsh[++Now],Sum+=(LL)hsh[Now]*Now;
        Ans+=Sum-((LL)Num-K)*Now;
    }
    printf("%lld\n",Ans);
    return 0;
}

这道题等我后面学习一下再看吧

C——逃离幻想乡
题目描述
“来世愿生幻想乡”,这是多少东方迷的心愿啊。

但是……

“来世想生在幻想乡的各位,小心到时候我的儿子看你们的本子……” 某易云音乐上的网友语惊四座。

没想到,这件事情闹得沸沸扬扬,竟然连远在幻想乡的灵梦也知道了,于是灵梦打算带领一众妖精们逃离幻想乡,前往新的乌托邦。

正当一众妖精再有说有笑的赶路时,在最前头的紫妈突然停了下来,原来是有一个结界拦住了去路,上面写着:

结果妖精刚通过没多久,却发现前面有一个万丈深渊,峭壁上还有几行大字:

妖精们啊,你们只需算出,对于一个整数m(0≤m≤n)有多少个2m在10进制下第一个数字为
L
L就可以召唤深渊巨龙(神龙)通过这里。

仗着自己开了一个红茶馆(雾),大小姐在1e-9秒内就算出了答案ans1。

成功通过深渊后,妖精们来到了幻想乡之门前,只见门前插了3根擎天巨柱,其中最左边的柱子上有2*ans1个翡翠方块,而翡翠方块刚好从上到下依次增大且每种尺寸的翡翠方块有两块,也就是说:一共有ans1 种翡翠方块,妖精们走进一看,发现同一尺寸的翡翠方块竟然还分颜色:上面的翡翠方块为黑色,下面的翡翠方块为白色。最下面的翡翠方块上刻了一行小字:

妖精们啊,若要出此幻想乡,你们须将所有的翡翠从左边的定海柱移至最右边的定天柱上,并且遵从以下规则:

1.大的翡翠方块不能放在小的翡翠方块上面
2.当所有的翡翠方块移动完毕时,定天柱上的方块黑白顺序必须和定海柱上的方块黑白顺序相同

仗着机敏的头脑,琪露诺在1e-9秒内就算出了最少的移动次数ans2

妖精们齐心协力将所有方块移到右边的柱子上的后,突然幻想乡之门炸裂了,随后整个幻想乡的空间出现龟裂,原来,这个装置便是幻想乡的毁灭装置。

现在灵梦她们自由了,她们可以前往她们自己的乌托邦去了。

临走前,灵梦为了考验一下作为蒟蒻的YPC,所以就让蒟蒻YPC告诉她这一路上的ans1 ans2分别是多少,由于YPC非常蒻,所以就前来询问各位巨佬了,希望你们能求出ans1 ans2的值,注意将ans2对1000000007取模(YPC温馨提醒:模运算在Pascal下为mod,在C++下为*%*)。
输入描述:
一行2个数字n,
L
L。
输出描述:
第一行一个数表示ans1,第二行一个数表示ans2。

示例1
输入
10 3
输出
1
3
ps:不多bb,上神鞪的代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1000000007;


ll q_pow(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1)
        {
            ans=(ans*a)%mod;
        }
        a=(a*a)%mod;
        b>>=1;
    }
    return ans;
}

int main(){
	ll n,l,ans1=0,ans2=0,sum1;
    cin>>n>>l;
   if(l==1)ans1=1;
    else ans1=0;
    ll s=2;
    for(int i=1;i<=n;i++){
        ll t=s;
        while(t>=10)t/=10;
        if(t==l) ans1++;
        s*=2;
        if(s>99999999999999999LL)s/=10;
    }
    ans2=(q_pow(2,ans1)-1)*4-1;
    ans2%=mod;
    cout<<ans1<<endl<<ans2<<endl;
	return 0;
}

和大佬们比起来我还是太菜了,还要继续努力啊

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值