Namomo Test Round 2(A题和B题)

3 篇文章 0 订阅
2 篇文章 0 订阅

A.请求配对
题目描述:你初始有2n个数字,答案初始为1
现在需要做n次操作,每次从这些数字中取出两个数字 x,y 并从原数字集合中删除,将答案乘以 x+y
现在需要找到一种方案使得答案最大,由于答案可能很大,需要将最大答案模 1e9+7 输出。

算法:贪心
只要每一次,选择当前剩下的序列中最大的和最小的相加并乘到答案上,最后得到的就是最大的。

wck:窝当时就是凭感觉做的,感觉差不多就用的这个策略。证的话肯定能证,但是我不会。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rt long long
#define M 1000000007 
using namespace std;
inline rt read()
{
 register char ch=getchar();register rt u=0,v=0;
 while(!isdigit(ch)){if(ch=='-')v=1;ch=getchar();}
 while(isdigit(ch)){u=u*10+ch-'0';ch=getchar();}
 return v?-u:u;
}
rt n,ans=1;
rt an[200010];
int main()
{
 n=read();
 for(int i=1;i<=n*2;i++)
 an[i]=read();
 sort(an+1,an+n*2+1);
 for(int i=n*2;i>=n+1;i--)
  ans=ans*((an[i]+an[n*2-i+1])%M)%M;
 ans=(ans%M+M)%M;
 printf("%lld",ans);
 return 0;
}

B.Namomo字符串(一看就是原创题)
题目描述:我们定义一个串 Snamomo串,当且仅当:

串长度为偶数,并且所有奇数下标位置字符都是辅音,所有偶数下标位置字符都是元音,这里下标从 1 开始,元音指a,e,i,o,u这些字符,而辅音是除了元音以外的所有小写字符。
串长大于等于 6 ,并且从第三个字符开始是一个循环节为 2 的串,也就是有 S3=S5=⋯=S∣S∣−1,S4=S6=⋯=S∣S∣

比如namomo, mifafa, namomomomo, momomo, vuvovo是namomo串,而namymy, momo, namomom不是namomo串。
现在给你一个字符串 S ,问有多少个子串是namomo串

算法:简单哈希
首先找Namomo串最关键的就是后面那个循环节为2的串,也就是说,我们要在给出的字符串中,找出某一段长度为4及以上循环节为2并且是辅音+元音组合的串,例如:momo,vovovo,nananana,我们命名为momo串
怎么样找momo串呢?最快捷的方法就是用hash求单独的相连辅音+元音的组合的hash值并存入数组中,然后进行简单比对,找到连续相等且长度满足条件的一段就是一个momo串,我们找到momo串之后有两种情况,第一种是他自身长度已经大于6,可以作为一个单独的Namomo串,另一种是需要在加上前面那个。

例如样例2
namymyxmomoxnamomom
提取出对应的部分就是
na mo mo na mo mo
1 8 10 13 15 17‘
下面的数字是对应的位置。
发现两个momo串,分别是起始点为8,长度为4的一个和起始点为15且长度为4的一个,分别来看,第一个momo串前面啥也没有所以不能构成namomo串,第二个前面正好有一个na,所以能构成namomo串。
什么,你问我长度为6或者更大的时候?
简单,长度>=6的时候要分别算自己组成和加上前面两种情况,式子都在代码里,不多BB了

wck:这个题目单纯区分了元音和辅音,并且不会有交集,这就让这个题不会出现重叠的情况,方便了很多

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rt long long
#define M 1000000007 
#define p 131
#define ull unsigned long long
using namespace std;
inline rt read()
{
 register char ch=getchar();register rt u=0,v=0;
 while(!isdigit(ch)){if(ch=='-')v=1;ch=getchar();}
 while(isdigit(ch)){u=u*10+ch-'0';ch=getchar();}
 return v?-u:u;
}
char as[500010];
rt l,an[500010],loc[500010],tot,ans;
ull mm[500010];
bool judge(char c){return (c=='a'||c=='e'||c=='i'||c=='o'||c=='u');}
int main()
{
 scanf("%s",as+1);
 l=strlen(as+1);
 for(int i=1;i<=l;i++)
 if(judge(as[i]))an[i]=1;
 else an[i]=0;
 for(int i=1;i<=l;i++)
 if(an[i]==0&&an[i+1]==1&&i<l)
 {
  ull hsh=as[i]*p+as[i+1];
  mm[++tot]=hsh;
  loc[tot]=i;
 }
// for(int i=1;i<=tot;i++)
// printf("%lld %lld\n",loc[i],mm[i]);
 rt k=1,ll=1,rr=1;
 while(k<=tot)
 {
  if(mm[k+1]==mm[k]&&loc[k+1]==loc[k]+2)
   rr=k+1;
  else
  {
  // printf("%lld %lld %lld ",ans,ll,rr);
   if(rr-ll+1>=2)
   {
    rt len=(rr-ll+1);
    if(ll>=2&&loc[ll-1]==loc[ll]-2)
    ans+=(len-1),ans+=(len-2)*(len-1)/2;
    else
    ans+=(len-2)*(len-1)/2;
   }
  // printf("%lld\n",ans);
   ll=k+1;
   rr=k+1;
  }
  k++;
 }
 printf("%lld",ans);
 return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值