Codeforces Round #499 (Div. 2)

本文解析了CodeForces平台上的六道算法竞赛题目,包括字符串处理、贪心算法、二分搜索、递归求解等核心算法思想。针对每一道题目,提供了详细的解题思路及代码实现。

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

比赛链接

https://codeforces.com/contest/1011

题解

A. Stages

题目大意

给定一个长度为 n n 的字符串S,找出 k k 个在S中出现的字母,使得这 k k 个字母在字母表中不相邻。如果不存在输出1,如果存在输出最小的“重量”之和,其中a的重量为1,b的重量是2……

1kn50 1 ≤ k ≤ n ≤ 50

题解

直接按照题意模拟即可。

B. Planning The Expedition

题目大意

总共有 m m 份食物,每份食物都有一个种类ai,现在有 n n 个人,每个人每天只能吃一种食物,不同的人可以吃不同的食物。问这些食物最多能维持多少天。

1n,m,ai100

题解

二分答案,二分出来答案就很好判定了。

C. Fly

题目大意

n n 个行星,每个行星都有一个启动系数ai和降落系数 bi b i ,代表起飞/降落时一单位燃料能够推动的飞船+燃料的重量。现在有一个飞船,重量为 m m ,要从一号行星起飞到二号行星降落,再从二号行星起飞到三号行星降落,……,一直到n号行星降落,最后从 n n 号行星起飞到一号行星降落。求飞船起飞时需要携带的最小燃料。

1n,m,ai,bi1000

题解

倒着推,如果起飞/降落系数为 k k ,起飞/降落后的重量为b,需要携带的燃料为 x x ,那么

x=bk1

按照逆序求需要携带的燃料。

D. Rocket

题目大意

交互题,要你猜一个数字,大于你猜的数字返回1,小于则返回-1,等于返回0,有可能会出错,出错的状态是一个循环。或者说,若返回的结果为 k k ,真实的结果为v,当前是第 i i 次猜测,出错状态的长度为n,则 k=pi mod n×v k = p i   m o d   n × v 。最多猜测60次。

n30 n ≤ 30 ,数字大小 109 ≤ 10 9

题解

n n 次都猜i,如果得到 0 0 那么就返回,否则得到的结果一定是1,如果没有得到 1 1 说明出错了。通过这种方法能得到p,最后二分查找 [n+1,109] [ n + 1 , 10 9 ] ,有了 p p 很容易得到正确的结果。

E. Border

题目大意

给出n个值 v1,v2,,vn v 1 , v 2 , ⋯ , v n ,判断这些值通过加法能够凑出模 k k 意义下最后一位为多少的值,可以重复使用同一个值。

n,k105,vi109

题解

如果有 m m 个值a1,a2,,am能被凑出来,设 x=gcd(a1,a2,,am) x = gcd ( a 1 , a 2 , ⋯ , a m ) ,那么一定有:

a1=0,a2=x,a3=2x,,am=(m1)x,x|d a 1 = 0 , a 2 = x , a 3 = 2 x , ⋯ , a m = ( m − 1 ) x , x | d

考虑 g=gcd(v1,v2,,vn) g = gcd ( v 1 , v 2 , ⋯ , v n ) ,显然上面式子的 x=g x = g 。那么答案就可以枚举得到了。

F. Mars rover

题目大意

给一棵 n n 个节点的数,每个节点有以下属性:

IN:0个儿子,值为本身的值;

AND:2个儿子,值为左儿子的值and右儿子的值;

XOR:2个儿子,值为左儿子的值xor右儿子的值;

OR:2个儿子,值为左儿子的值or右儿子的值;

NOT:1个儿子,值为not儿子的值。

求改变一个IN节点对根节点值的影响,注意一次只有一个IN节点的值被改变了。

n106

题解

首先dfs一边求出每个节点的值,然后再一次dfs,考虑如果当前节点的值改变能让根节点的值改变,它的儿子应该怎样改变才能让根节点的值改变。

AND:只要另一个儿子值为1,这个儿子改变了就会使这个节点的值发生改变。

XOR:无论如何,一个儿子改变了这个点的值就会改变。

OR:只要另一个儿子的值为0,这个儿子改变了就会使这个点的值发生改变。

NOT:儿子改变了这个点的值就会改变。

dfs一边即可。

代码

A. Stages

#include <cstdio>

const int maxn=50;

int n,k,f[30];
char s[maxn+3];

int main()
{
  scanf("%d%d%s",&n,&k,s+1);
  for(int i=1; i<=n; ++i)
    {
      f[s[i]-'a'+1]=1;
    }
  int ans=0,tot=0;
  for(int i=1; i<=26; ++i)
    {
      if(f[i])
        {
          ++tot;
          ans+=i;
          f[i+1]=0;
          if(tot==k)
            {
              break;
            }
        }
    }
  if(tot<k)
    {
      puts("-1");
    }
  else
    {
      printf("%d\n",ans);
    }
  return 0;
}

B. Planning The Expedition

#include <cstdio>

const int maxn=100;

int read()
{
  int x=0,f=1;
  char ch=getchar();
  while((ch<'0')||(ch>'9'))
    {
      if(ch=='-')
        {
          f=-f;
        }
      ch=getchar();
    }
  while((ch>='0')&&(ch<='9'))
    {
      x=x*10+ch-'0';
      ch=getchar();
    }
  return x*f;
}

int n,m,a[maxn+10],f[maxn+10];

int check(int x)
{
  int sum=0;
  for(int i=1; i<=100; ++i)
    {
      sum+=f[i]/x;
    }
  if(sum>=n)
    {
      return 1;
    }
  else
    {
      return 0;
    }
}

int main()
{
  n=read();
  m=read();
  for(int i=1; i<=m; ++i)
    {
      a[i]=read();
      ++f[a[i]];
    }
  int l=1,r=m;
  while(l<=r)
    {
      int mid=(l+r)>>1;
      if(check(mid))
        {
          l=mid+1;
        }
      else
        {
          r=mid-1;
        }
    }
  printf("%d\n",l-1);
  return 0;
}

C. Fly

#include <cstdio>

const int maxn=1000;

int read()
{
  int x=0,f=1;
  char ch=getchar();
  while((ch<'0')||(ch>'9'))
    {
      if(ch=='-')
        {
          f=-f;
        }
      ch=getchar();
    }
  while((ch>='0')&&(ch<='9'))
    {
      x=x*10+ch-'0';
      ch=getchar();
    }
  return x*f;
}

int n,m,a[maxn+10],b[maxn+10];
double w;

int main()
{
  n=read();
  m=read();
  for(int i=1; i<=n; ++i)
    {
      a[i]=read();
    }
  for(int i=1; i<=n; ++i)
    {
      b[i]=read();
    }
  for(int i=1; i<=n; ++i)
    {
      if((a[i]<=1)||(b[i]<=1))
        {
          puts("-1");
          return 0;
        }
    }
  w=m+(1.0*m)/(b[1]-1);
  for(int i=n; i>=2; --i)
    {
      w+=w/(a[i]-1);
      w+=w/(b[i]-1);
    }
  w+=w/(a[1]-1);
  printf("%.7lf\n",w-m);
  return 0;
}

D. Rocket

#include <cstdio>

const int maxn=30;

int n,m,p[maxn+3];

int main()
{
  scanf("%d%d",&n,&m);
  for(int i=1; i<=m; ++i)
    {
      printf("%d\n",i);
      fflush(stdout);
      scanf("%d",&p[i]);
      if(p[i]==0)
        {
          return 0;
        }
    }
  int l=m+1,r=n,i=1;
  while(l<=r)
    {
      int mid=(l+r)>>1;
      printf("%d\n",mid);
      fflush(stdout);
      int x;
      scanf("%d",&x);
      x*=p[i];
      if(x==0)
        {
          return 0;
        }
      else if(x==1)
        {
          l=mid+1;
        }
      else
        {
          r=mid-1;
        }
      ++i;
      if(i>m)
        {
          i=1;
        }
    }
  return 0;
}

E. Border

#include <cstdio>

const int maxn=100000;

int read()
{
  int x=0,f=1;
  char ch=getchar();
  while((ch<'0')||(ch>'9'))
    {
      if(ch=='-')
        {
          f=-f;
        }
      ch=getchar();
    }
  while((ch>='0')&&(ch<='9'))
    {
      x=x*10+ch-'0';
      ch=getchar();
    }
  return x*f;
}

int ans,n,k;

int gcd(int a,int b)
{
  return b?gcd(b,a%b):a;
}

int main()
{
  n=read();
  k=read();
  for(int i=1; i<=n; ++i)
    {
      int a=read();
      ans=gcd(gcd(a,k),ans);
    }
  printf("%d\n",k/ans);
  for(int i=0; i<k; i+=ans)
    {
      printf("%d ",i);
    }
  puts("");
  return 0;
}

F. Mars rover

#include <cstdio>

const int maxn=1000000;

struct node
{
  int op,val,id;
  node *son[2];
};

node t[maxn+10],*root;
int n,cnt,ans[maxn+10];

int getval(node *u)
{
  if(u->op==0)
    {
      return u->val;
    }
  else if(u->op==1)
    {
      return u->val=(getval(u->son[0])&getval(u->son[1]));
    }
  else if(u->op==2)
    {
      return u->val=(getval(u->son[0])^getval(u->son[1]));
    }
  else if(u->op==3)
    {
      return u->val=(getval(u->son[0])|getval(u->son[1]));
    }
  else
    {
      return u->val=(!getval(u->son[0]));
    }
}

int getans(node* u)
{
  if(u->op==0)
    {
      ans[u->id]=!ans[u->id];
      return 0;
    }
  else if(u->op==1)
    {
      if(u->son[0]->val==1)
        {
          getans(u->son[1]);
        }
      if(u->son[1]->val==1)
        {
          getans(u->son[0]);
        }
    }
  else if(u->op==2)
    {
      getans(u->son[0]);
      getans(u->son[1]);
    }
  else if(u->op==3)
    {
      if(u->son[0]->val==0)
        {
          getans(u->son[1]);
        }
      if(u->son[1]->val==0)
        {
          getans(u->son[0]);
        }
    }
  else if(u->op==4)
    {
      getans(u->son[0]);
    }
  return 0;
}

int main()
{
  scanf("%d",&n);
  for(int i=1; i<=n; ++i)
    {
      char op[10];
      int l,r;
      scanf("%s",op);
      if(op[0]=='I')
        {
          scanf("%d",&l);
          t[i].op=0;
          t[i].val=l;
          t[i].id=++cnt;
        }
      else if(op[0]=='A')
        {
          scanf("%d%d",&l,&r);
          t[i].op=1;
          t[i].son[0]=&t[l];
          t[i].son[1]=&t[r];
        }
      else if(op[0]=='X')
        {
          scanf("%d%d",&l,&r);
          t[i].op=2;
          t[i].son[0]=&t[l];
          t[i].son[1]=&t[r];
        }
      else if(op[0]=='O')
        {
          scanf("%d%d",&l,&r);
          t[i].op=3;
          t[i].son[0]=&t[l];
          t[i].son[1]=&t[r];
        }
      else if(op[0]=='N')
        {
          scanf("%d",&l);
          t[i].op=4;
          t[i].son[0]=&t[l];
        }
    }
  root=&t[1];
  getval(root);
  for(int i=1; i<=cnt; ++i)
    {
      ans[i]=root->val;
    }
  getans(root);
  for(int i=1; i<=cnt; ++i)
    {
      printf("%d",ans[i]);
    }
  puts("");
  return 0;
}
基于Spring Boot搭建的一个多功能在线学习系统的实现细节。系统分为管理员和用户两个主要模块。管理员负责视频、文件和文章资料的管理以及系统运营维护;用户则可以进行视频播放、资料下载、参与学习论坛并享受个性化学习服务。文中重点探讨了文件下载的安全性和性能优化(如使用Resource对象避免内存溢出),积分排行榜的高效实现(采用Redis Sorted Set结构),敏感词过滤机制(利用DFA算法构建内存过滤树)以及视频播放的浏览器兼容性解决方案(通过FFmpeg调整MOOV原子位置)。此外,还提到了权限管理方面自定义动态加载器的应用,提高了系统的灵活性和易用性。 适合人群:对Spring Boot有一定了解,希望深入理解其实际应用的技术人员,尤其是从事在线教育平台开发的相关从业者。 使用场景及目标:适用于需要快速搭建稳定高效的在线学习平台的企业或团队。目标在于提供一套完整的解决方案,涵盖从资源管理到用户体验优化等多个方面,帮助开发者更好地理解和掌握Spring Boot框架的实际运用技巧。 其他说明:文中不仅提供了具体的代码示例和技术思路,还分享了许多实践经验教训,对于提高项目质量有着重要的指导意义。同时强调了安全性、性能优化等方面的重要性,确保系统能够应对大规模用户的并发访问需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值