Codeforces Round#539(Div. 2)

本文分享了作者在CodeForces平台上的训练经历,详细解析了三道算法题的解题思路,包括模拟题、磁力机问题及有趣的对称对问题。通过代码示例,展示了如何利用前缀和、质数特性等技巧高效解决问题。

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

第一次写博客,记录一下cf的训练过程,以激励自己吧。在这之前消沉了很长一段时间,才发现和同龄人差距越来越大,如果努力都不努力,那谈何抱怨天赋能力呢?
A. Sasha and His Trip
简单的模拟题,思路对了即可。
我的思路是:因为越远油价越贵。所以先判断能否在一开始就把到达目的地的油加完,如果不行的话将油箱加满,之后每到一个城市加一次油。

#include<bits/stdc++.h>
using namespace std;
#define lld %I64d
#define REP(i,k,n) for(int i=k;i<n;i++)
#define REPP(i,k,n) for(int i=k;i<=n;i++)
#define mst(a,k)  memset(a,k,sizeof(a))
#define LL long long
#define N 100005
#define mod 1000000007
#define INF 2147483646

int main()
{
   int n,v;
   scanf("%d %d",&n,&v);
   if(n-1<=v)
    printf("%d\n",n-1);
   else
   {
       int num=n-v-1;
       int ans=0;
       REPP(i,1,num)
       {
           ans+=i+1;
       }
       printf("%d\n",ans+v);
   }
}

B. Sasha and Magnetic Machines
依旧可以暴力模拟,一开始没有左右两个数字都遍历寻找,所以t了一次。实际上左侧的数字应该是数列中最小的数字收益最大。然后遍历寻找右侧数字以及x,以找到使总和变得最小的方案。
num=min(num,(x-1)*(mi-a[i]/x));
注意到数组里面的数字均小于100,还做了一些关于质数的剪枝,但实际上不写应该也没有影响。

#include<bits/stdc++.h>
using namespace std;
#define lld %I64d
#define REP(i,k,n) for(int i=k;i<n;i++)
#define REPP(i,k,n) for(int i=k;i<=n;i++)
#define mst(a,k)  memset(a,k,sizeof(a))
#define LL long long
#define N 100005
#define mod 1000000007
#define INF 2147483646
inline int read(){int s=0;char ch=getchar();for(; ch<'0'||ch>'9'; ch=getchar());for(; ch>='0'&&ch<='9'; ch=getchar())s=s*10+ch-'0';return s;}

int a[N];
int flag[105];
int zhi[25]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97};
int main()
{
   int n;
   mst(flag,0);
   REP(i,0,25)
   {
       flag[zhi[i]]=1;
   }
   scanf("%d",&n);
   int mi=100,ma=0,sum=0;
   REP(i,0,n)
   {
       scanf("%d",&a[i]);
       sum+=a[i];
       mi=min(mi,a[i]);
   }
   int x,num,ans=0;
   REP(i,0,n)
   {
       if(flag[a[i]]==1)
        continue;
       x=0,num=0;
       while(1)
       {
           x++;
           if(a[i]%x)
            continue;
           if(mi*x>=a[i]/x)
           {
               num=min(num,(x-1)*(mi-a[i]/x));
               break;
           }
           num=min(num,(x-1)*(mi-a[i]/x));
       }


       ans=min(ans,num);

   }
   printf("%d\n",sum+ans);
}

Γ(z)=∫0∞tz−1e−tdt&ThinSpace;. \Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,. Γ(z)=0tz1etdt.
C. Sasha and a Bit of Relax
这题知道结论思维正确的话很快就能解决(然而我没有QAQ)
这题有一个前提结论首先应该了解:
设前缀和数组pref(i)=a1⊕a2⊕…⊕ai. 那么al⊕al+1⊕…⊕ar=pref(r)⊕pref(l-1)。正常应该是自己都能推出来的,我后来问dalao才反应过来这一点。
这道题一开始我题目读错了,以为是mid左侧所有元素异或==mid右侧所有元素异或,以错误的思路做了一个小时。
实际上的做法:设xor[x,y]表示从x到y异或和。则xor[l,mid-1]==xor[mid,r]就可以转化为xor[l,r]==0。即求所有异或和为0的偶数长度子段。继续简化一下就是求pref(l-1)==pref®。
这样我们就可以利用一个区分奇偶数的前缀和桶结构来求出所有的funny pairs。
特别要注意的点是:例如2 2的样例会判错。原因是一开始时0 也在偶数位上出现了,需加入桶中。
详见代码:

#include<bits/stdc++.h>
using namespace std;
#define lld %I64d
#define REP(i,k,n) for(int i=k;i<n;i++)
#define REPP(i,k,n) for(int i=k;i<=n;i++)
#define mst(a,k)  memset(a,k,sizeof(a))
#define LL long long
#define N 300005
#define mod 1000000007
#define INF 0x3f3f3f3f
inline int read(){int s=0;char ch=getchar();for(; ch<'0'||ch>'9'; ch=getchar());for(; ch>='0'&&ch<='9'; ch=getchar())s=s*10+ch-'0';return s;}
int a[N];
#define num (1<<20)+10
int odd[num],eve[num];//桶结构分开保存奇偶
int main()
{
    LL ans=0;
    int n=read();
    a[0]=0;
    REPP(i,1,n)
    {
        a[i]=read();
    }
    eve[0]++;
    int pre=0;
    REPP(i,1,n)
    {
        pre^=a[i];
        if(i&1)
        {
            ans+=odd[pre];//加上在此之前这个前缀和出现的次数
            odd[pre]++;
        }
        else
        {
            ans+=eve[pre];
            eve[pre]++;
        }
    }
    printf("%lld\n",ans);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值