Codeforces Global Round 1 (A-E题解)

Codeforces Global Round 1

题目链接:https://codeforces.com/contest/1110

A. Parity

题意:

给出{ak},b,k,判断a1*b^(k-1)+a2*b^(k-2)+...+ak*b^0的奇偶性。

题解:

暴力求模2意义下的值就好了。

代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5+5;
int n;
int b,k;
int a[N];
ll qp(ll A,ll B){
    ll ans = 1;
    while(B){
        if(B&1) ans=ans*A%2;
        A=A*A%2;
        B>>=1;
    }
    return ans;
}
int main(){
    cin>>b>>k;
    for(int i=1;i<=k;i++) scanf("%d",&a[i]);
    int t=b%2;
    int sum = 0;
    for(int i=k-1;i>=0;i--){
        sum=sum+a[k-i]*qp(t,i);
        sum%=2;
    }
    if(sum&1) cout<<"odd";
    else cout<<"even";
    return 0;
}

B. Tape

题意:

在[1,m]这个区间中,有n个点,现在要用k个木棍去覆盖完这些点,问最短覆盖长度为多少。

题解:

首先将起始点和终点间的距离求出来,然后考虑将不需要的一些覆盖给减去。

具体做法就是用优先队列保存两个相邻点之间的间隔,然后不断取最大的间隔减去,最后使得剩下的区间还剩下k个即可。

代码如下:

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N = 1e5+5;
int n,m,k;
ll a[N],d[N];
ll ans;
int main(){
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;i++) scanf("%I64d",&a[i]);
    ans=a[n]-a[1]+1;
    priority_queue <ll> q;
    for(int i=1;i<n;i++){
        d[i]=a[i+1]-a[i];
        q.push(d[i]-1);
    }
    int cnt = 1;
    while(cnt<k){
        ll now = q.top();q.pop();
        cnt++;
        ans-=now;
    }
    cout<<ans;
    return 0;
}

C. Meaningless Operations

题意:

有多个询问,每次询问会输入一个数a,然后对于所有的数b(1<=b<a),求max{ gcd(a&b,a^b) }。

题解:

这个可以打表来做。

如果想的话,就是分两种情况考虑:一种是所有二进制位数都为1,另一种就是并非这样。

第二种思考起来比较简单,答案肯定为2^x-1,我们取的b只需要刚好把a二进制中的0填补就行了。

第一种情况会有一个这样的性质:a&b+a^b=a。现在设g=gcd(a&b,a^b),所以现在有g|a&b,g|a^b,那么自然有g|a。

我们会发现g其实为a的因子,那么这种情况找a的最大因子就好啦。

代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int q;
ll a;
ll p2[30];
ll Print(ll x){
    for(ll i=3;i*i<=x;i++){
        if(x%i==0){
            return x/i;
        }
    }
    return 1;
}
int main(){
    cin>>q;
    p2[0]=1;
    for(int i=1;i<=26;i++) p2[i]=p2[i-1]*2;
    while(q--){
        cin>>a;
        int i;
        for(i=26;i>=0;i--) if((1<<i)&a) break ;
        if(a&(a+1)) cout<<p2[i+1]-1<<endl;
        else cout<<Print(a)<<endl;
    }
    return 0;
}

D. Jongmah

题意:

给出n个数,数的大小不超过m,问最多有多少个类似于(x,x,x),(x-1,x,x+1)这样的三元组,每个数最多用一次。

题解:

对于我这样的蒟蒻来说,dp方程式理解了很久,感觉十分巧妙。

首先,就是对于类似于(x-1,x,x+1)这样的三元组来说,我们只需要考虑不超过三个的情况就可以了。因为当其超过三个时,直接选(x,x,x)这种类型得到的答案是一样的。

设dp(i,j,k)的定义为:当前在i这个位置,有j个(i-1,i,i+1)三元组,有k个(i,i+1,i+2)这样的三元组。

转移的话就从(i-2,i-1,i),(i-1,i,i+1) (即i-1)转移过来,我们在计算的时候附加上(x,x,x)这种类型就好了。

因为每次都从i-1转移过来,所以还可以用滚动数组优化掉一维,但是不优化对于这题也没啥影响~

代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6+5;
int n,m;
int a[N],dp[N][3][3];
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        int x;
        scanf("%d",&x);
        a[x]++;
    }
    for(int i=1;i<=m;i++){
        for(int j=0;j<3;j++){
            for(int k=0;k<3;k++){
                for(int l=0;l<3;l++){
                    if(l+j+k>a[i]) continue ;
                    dp[i][k][l]=max(dp[i][k][l],dp[i-1][j][k]+l+(a[i]-l-k-j)/3);
                }
            }
        }
    }
    cout<<dp[m][0][0];
    return 0;
}

E. Magic Stones

题意:

给出两个数列{cn},{tn},现在可以进行一些变化,比如对于ci来说,可以让ci=ci-1+ci+1-c(2<=i<n),变化的次数以及位置不限,问是否最后能得到t数列。

题解:

这题也比较巧妙吧,首先判断一下首尾可以知道是否可行。

之后根据这个式子,利用差分数组来解。

设di=ci+1-ci,那么当ci变化后,di=ci‘-ci-1=ci+1-ci=di+1,di+1=di,也就是说,两个差分数组相当于换了下位置。

也就是说,题目中的操作,实质上是不断交换差分数组的位置。

之后就有很多种方法了,给出我的代码吧:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5+5;
int n;
ll c[N],t[N],d[N];
multiset <ll> s;
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&c[i]);
    for(int i=1;i<=n;i++) scanf("%d",&t[i]);
    if(c[1]!=t[1] || c[n]!=t[n]){
        cout<<"No";
        return 0;
    }
    for(int i=1;i<n;i++) d[i]=c[i+1]-c[i],s.insert(d[i]);
    for(int i=2;i<=n;i++){
        ll need = t[i]-t[i-1];
        auto it = s.lower_bound(need);
        if(*it==need){
            s.erase(it);
        }else{
            cout<<"No";
            return 0;
        }
    }
    cout<<"Yes";
    return 0;
}

除开这种,还可以求出t数列的差分数组,然后对两个差分数组进行排序来比较,实现方法比我简单多了。

原文地址:https://www.cnblogs.com/heyuhhh/p/10356403.html

时间: 2024-10-05 19:36:41

Codeforces Global Round 1 (A-E题解)的相关文章

【手抖康复训练1 】Codeforces Global Round 6

[手抖康复训练1 ]Codeforces Global Round 6 总结:不想复习随意打的一场,比赛开始就是熟悉的N分钟进不去时间,2333,太久没写题的后果就是:A 题手抖过不了样例 B题秒出思路手抖过不了样例,C题秒出思路手抖过不了样例*3 D题 手抖 过的了样例 ,调了1h,赛后发现变量名写错了,改一个字符就能AC... 题目等补完题一起放上来QAQ 原文地址:https://www.cnblogs.com/ttttttttrx/p/12110199.html

Codeforces Global Round 7【ABCD】(题解)

目录 涵盖知识点:思维.构造.马拉车. 比赛链接:传送门 D题只有数据范围的区别,故只写D2. 好多题啊,随缘更新.(其实懒得写) A - Bad Ugly Numbers B - Maximums C - Permutation Partitions D2 - Prefix-Suffix Palindrome (Hard version) 涵盖知识点:思维.构造.马拉车. 比赛链接:传送门 D题只有数据范围的区别,故只写D2. 好多题啊,随缘更新.(其实懒得写) A - Bad Ugly Nu

codeforces global round 1题解搬运

A,B很简单,跳过了. C题规律相当明显,可以直接对\(2^n-1\)打表,也可以不打表直接算最大因数. D题两种操作转化一下DP即可. E题考虑查分数组不变的性质. F题考虑dfs时动态维护每个叶子的深度,从一个节点走向它的孩子相当于孩子对应的区间加,不包含孩子的区间减. #include <bits/stdc++.h> using namespace std; typedef long long ll; const int P=1050000; const int N=500010; in

Codeforces Global Round 3 题解

A 送分题 B 送分题 C 考虑先依次把\(2\sim n-1\)换到正确的位置,这个只要利用\(1,n\)两个位置交换就行了. 然后如果\(n\)在第一位就交换\(1,n\). D 显然\(a<b\)和\(a>b\)的可以分别考虑.不失一般性考虑\(a<b\)的.那么相当于要选出若干二元组并排序,要求满足\(b_i>a_{i+1}\).考虑对数值建点,\(a\)向\(b\)连边,所有\(i\)向\(i-1\)连边,相当于要走一条路径经过最多\(a->b\)的边.这样可以直观

Codeforces Global Round 4 题解

技不如人,肝败吓疯…… 开场差点被 A 题意杀了,幸好仔细再仔细看,终于在第 7 分钟过掉了. 跟榜.wtf 怎么一群人跳题/倒序开题? 立刻紧张,把 BC 迅速切掉,翻到了 100+. 开 D.感觉有点吓人……感觉有点可做? 的确挺可做.再切掉 D,但是此时已经到 300+ 了. 没事,还能翻. 开 E.这……什么玩意? 瞄了一眼 F1,…… 盯着这两题盯到自闭. 最后 rk 1000 左右.我的名字颜色真的是对的吗…… A 看懂题了就是水题.选上所有小于等于第一个党派一半人数的党派,如果不行

Codeforces Global Round 5 部分题解

tourist的劲题,掉了17分,着实心痛,本来是有分可恰到的 A.给你一个数列\(a\),你需要构造一个数列\(b\),使得每一个\(b\)都等于\(a/2\),向上或向下取整由你决定 并且还要使得\(\sigma b\)的总和等于0 数据是保证有解的 那么我们就令所有\(b\)等于\(\lfloor a/2 \rfloor\),求出总和 再遍历一遍数组,sum过大则把某些负数调整为向上取整,否则把正数调整 代码: #include <bits/stdc++.h> #define int l

Codeforces Global Round 7 题解

A 一种合法构造方式是\(299\cdots 9\) code B 发现每次的\(x_{i-1}\)都是知道的,于是可以直接递推. code C 最终答案所选的数一定是\(n-k+1\)到\(n\)的所有数.把这些数所在的位置记作\(p_1,p_2,\cdots,p_k\). 不难发现每个\(r_i\in [p_i,p_{i+1})\),于是答案就是\(\prod (p_{i+1}-p_i)\). code D 首先把首尾能构成回文的部分删掉,因为这部分一定会出现在答案中. 问题变成了在当前字符

【 Codeforces Global Round 1 B】Tape

[链接] 我是链接,点我呀:) [题意] x轴上有m个连续的点,从1标号到m. 其中有n个点是特殊点. 让你用k段区间将这n个点覆盖. 要求区间的总长度最小. [题解] 一开始假设我们需要n个胶带(即包含每一个点) 然后因为k<=n 所以可能胶带不够用. 那么就得一个胶带跨过两个点. 怎么选择最好呢? 可以把b[i]-b[i-1]-1处理出来排个序. (优先取较小的花费) 然后取前n-k个累加和sum. 因为每取一个就少用一段胶带. 然后sum+n就是答案了 [代码] import java.i

【Codeforces Global Round 1 C】Meaningless Operations

[链接] 我是链接,点我呀:) [题意] 给你一个a 让你从1..a-1的范围中选择一个b 使得gcd(a^b,a&b)的值最大 [题解] 显然如果a的二进制中有0的话. 那么我们就让选择的b的二进制中对应的位置为1 剩下全为0就好 这样a的二进制全都变成1之后就是答案了(gcd的右边是0). 但是如果a的二进制里面全是1的话. 就没办法这么构造了 这里有两种情况. ①.1的个数是偶数 那么就101010这样构造 另外一个数就是010101 答案就是010101转换成十进制 ②.1的个数是奇数