最近两场cf总结

博主分享了在Codeforces平台参加的两场比赛的总结,详细分析了每道题目的解题思路,涉及暴力模拟、动态规划、数学算法、前缀和DP、树形结构、线段树等多种算法。通过比赛,博主强调了代码能力和数学思维的重要性,并提供了部分题目的链接以供深入学习。
摘要由CSDN通过智能技术生成

最近做了两场cf,通过了当中所有的题目,稍稍做下总结
Codeforces Round #325 (Div. 1)
这场是我排名最靠前的一次(23),虽然04写的比较慢,但是幸运的猜出了03,05和06都是短代码的可做题,然而并没有时间去看,这说明代码能力还是很重要的
A:有n个小孩依次去看牙齿,每个小孩看的时候会对后面的小孩造成等差递减的伤害,假如小孩不能承受这个伤害就会逃跑,问最后有几个小孩去看了牙齿,n<=4000
分析:比较简单的题目,暴力模拟每个小孩的看牙情况,用一个数组记录小孩是否还在队列当中

B:给出一张3*n的地图,有些位置有列车,列车每次向左行驶两格,行人最初在第一列,每次向右走一格,之后可以决定向上或者向下走一格(不超出地图),问行人最后是否有可能到达最后一列。
分析:可以转换坐标系,变成行人每次向右走三格之后决定向上或向下,之后就是一个简单的dp

C:A最初只有一个苹果,B最初只有一个橘子,现在要你构造一个01串操作序列,假如操作是0,则B拿A当前所具有苹果和橘子,否则A对B做相同的事,要求最后A和B的苹果数之和为x,橘子数之和为y.( x,y<=1018 )

分析:是一道比较巧妙的数学题,比赛的时候用欧几里德算法带进去算了一下,正好满足!于是就通过了这题
题解给了一个不为人知的数据结构:https://en.wikipedia.org/wiki/Stern%E2%80%93Brocot_tree

D:D是一个挺无聊的折半暴搜,虽然很简单,但是还是码了我一个小时之久,主要是一开始题目看错了。。。。

E:n个数,从中选出一个非空集合,在另外选出一个数,要求集合的gcd不为1且这个gcd和另外选择的数互质

分析:比较常用的筛法,假如把题目变成选择两个不同的数,要求gcd为1,那么我们可以先求 cnt[x]x ,筛一遍之后,我们可以先忽略不同这个要求,那么gcd是x的倍数的选法就是 cnt[x]2 ,之后再套用莫比乌斯函数暴力容斥即可得到答案,最后再减去1的数目即可。
对于这道题,也类似搞搞,不同之处在于他要求所选集合gcd不为1,因此我们最后再剪掉选择集合gcd==1形成的方案数,而后面也可以用莫比乌斯暴力容斥
代码极短

#include<bits/stdc++.h>
using namespace std;
const int Maxn=10000002,M=1e9+7;
typedef long long Int;
int miu[Maxn],cnt[Maxn];
int n;
int xp[500020];
int main()
{
    xp[0]=1;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)xp[i]=(xp[i-1]+xp[i-1])%M;
    for(int i=1;i<=n;i++)
    {
        int x;scanf("%d",&x);
        cnt[x]++;
    }
    int ans=0;
    miu[1]=1;
    for(int i=1;i<Maxn;i++)
    {
        for(int j=i+i;j<Maxn;j+=i)
        {
            miu[j]-=miu[i];
            cnt[i]+=cnt[j];
        }
        if(!cnt[i]||!miu[i])continue;
        ans+=miu[i]*(xp[cnt[i]]-1)*(Int)(cnt[i]-n)%M;
        if(ans>=M)ans-=M;
        if(ans<0)ans+=M;
    }   
    printf("%d\n",ans);
}

F:给一个长<1000的数字串,给两个长度均为d且不含前导0的L和R,要求L~R之间有多少个串满足至少有一个长度>=d/2的子串是原数字串的子串。d<=50
这道题比赛的时候并没有人通过这道题,当时也是被吓的题目都没读过。然而今天读了一下,发现难度比我想象的要低很多。L~R之间有多少个满足的,看这样的数据范围很容易想到数位dp,关键是状态,由于要求是原串的子串,那么我们只需要知道当前匹配的最长原串子串是怎么样的即可。很容易想到后缀自动机,由于长度只有1000,那么总结点数也只有2000,放在状态里面一点也不过分。当然,后缀自动机只知道在那个节点还并不能知道当前串长是多少,由于d只有50,我们可以在一维代表长度,转移的时候暴力枚举填充的数就可以通过这道题

#include<bits/stdc++.h>
using namespace std;
const int Maxn=2020,M=1e9+7;
string s;
int last,sz;
int ml[Maxn],f[Maxn],ch[Maxn][1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值