Codeforces Round #682 (Div. 2)

58 篇文章 0 订阅
35 篇文章 1 订阅

A. Specific Tastes of Andre

题意:给一个n,要求构造一个数组,需要让数组每个子串的和都能整除子串的长度。

思路:显然。只要让所有数都一样不就完了吗。子串和 = 子串长度*x,x任取。

AC代码:

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6+7;
const int mod = 1e9+7;
int t,n,m,k;
int a[N];

signed main(){
    int t;
    cin>>t;
    while(t-- ){
        cin>>n;
        for(int i = 0 ; i < n ; i ++){
            cout<<6<<" ";
        }
        cout<<endl;
    }
    return 0;
}

B. Valerii Against Everyone

题意:给定一个数组b,其实同时也给定了数组a,a[i] = 2b[i],问,在a中能不能找到两个不相交的子串,使得sum相等。子串长度可以为1。

思路:子串长度可以为1,这点很重要。选两个相等的元素不就满足题意了嘛。所以,数组中有相同元素的一定满足条件,那没有相同的元素的有没有可能满足条件呢。答案是不可能。考虑 比如 随便一个 2x,次方。如果要让另外一些数加起来等于2x,那必然需要凑到两个2x-1,但是数组中又不能有相等的元素。那就还得用2x-2,去凑。重复这个逻辑。直到20次方。因为没有相等元素,那么就不可能产生进位,不能产生进位,那么和加起来永远不可能等于另一个数。

AC代码:

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6+7;
const int mod = 1e9+7;
int t,n,m,k;
int a[N],b[N];
 
 
 
signed main(){
    int t;
    cin>>t;
    while(t-- ){
        cin>>n;
        map<int,int> mp;
        mp.clear();
        int flag = 0;
        for(int i = 0 ; i < n ; i ++)
        {
            cin>>a[i];
            mp[a[i]] ++;
            flag = flag || (mp[a[i]] >= 2);
        }
        if(flag)
            cout<<"YES"<<endl;
        else
            cout<<"NO"<<endl;
    }
    return 0;
}

C. Engineer Artem

题意:给定一个n*m的网格,现在想让这个网格中,所有的相邻的数字都不相等。但是每个数,最多只能变化一次,并且只能+1。

思路:一开始就想歪了,导致了一个小时的自闭。一开始就想着dfs,然后各种尝试剪枝。依然在case2就t飞了。看完题解直呼水题。只要让所有数组奇偶交替出现。那就满足题目要求了。所以+1,就足以改变一个数的奇偶性了。

AC代码:

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6+7;
const int mod = 1e9+7;
int t,n,m,k;
int a[104][105],b[105][105];
int mark[105][105];
 
 
signed main(){
    int t;
    cin>>t;
    while(t-- ){
        cin>>n>>m;
        for(int i = 0 ; i < n ; i ++){
            for(int j = 0 ; j < m ; j ++){
                cin>>a[i][j];
            }
        }
        for(int i = 0 ; i < n ; i ++){
            for(int j = 0 ; j < m ; j ++){
                if( (i+j)%2 ){
                    if(a[i][j]%2 == 0) a[i][j] ++;
                }else{
                    if(a[i][j]%2 == 1) a[i][j] ++;
                }
            }
        }
        for(int i = 0 ; i < n ; i ++){
            for(int j = 0 ; j < m ; j ++){
                cout<<a[i][j]<<" ";
            }
            cout<<endl;
        }
    }
    return 0;
}

D. Powerful Ksenia

题意:给定一个数组。和一种操作,这种操作是选择任意三个数,然后把这三个数都变成他们的异或和,问,能不能在n次操作之内,把所有数变成相同的。还要输出所有的操作。

思路:一次操作就可以把三个数变成相同的。 然后考虑这样的情况,i,j,k,i == j,那么操作之后,三个数都变成了k。于是,可以先把所有数变成两两相同的,然后再用一个保留的数,每次给两个数赋值。这样就可以变成相同的了。先对所有(2*i+1,2*i+2,2*i+3)操作,然后进行(2*i+1,2*i+2,n),的操作就行了,什么意思呢。

举个栗子:原数组:XYAJDIE。一次操作变成:TTTJDIE,两次:TTKKKIE,三次:TTKKZZZ,然后再把Z每次赋值两个,给前面所有值赋值。ZZKKZZZ,ZZZZZZZ。这是奇数的情况。
偶数的情况在遍历一遍之后会形成一个这样的:XXYYYZ,这样呢其实也是一样操作,但是要保证,最后YZ异或是等于0的。因为,题目求的就是所有数相同,那异或起来肯定是0了。所以原数组异或和如果不为0,则无解。否则,依然按照上一种情况处理。就可以变成ZZYYYZ,ZZZZYZ。为什么这样也行呢。因为Y和Z异或等于0,所以Y其实就等于Z!!

AC代码:

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6+7;
const int mod = 1e9+7;
int t,n,m,k;
int a[N],b[N];
struct node{
    int x,y,z;
    node(){};
    node(int i,int j,int k):x(i+1),y(j+1),z(k+1){};
}res[N];
 
void solve(){
    int cnt = 0;
    for(int i = 0 ; i+2 < n ; i += 2){
        res[cnt ++] = node(i,i+1,i+2);
    }
    for(int i = 0 ; i+2 < n ; i += 2){
        res[cnt ++] = node(i,i+1,n-1);
    }
    cout<<cnt<<endl;
    for(int i = 0 ; i < cnt ; i ++){
        cout<<res[i].x<<" "<<res[i].y<<" "<<res[i].z<<endl;
    }
}
 
 
signed main(){
    int t = 1;
    // cin>>t;
    while(t-- ){
        cin>>n;
        for(int i = 0 ; i < n ; i ++) cin>>a[i];
        if(n&1){
            cout<<"YES"<<endl;
            solve();
        }else{
            int tmp = 0;
            for(int i = 0 ; i < n; i  ++) tmp ^= a[i];
            if(tmp != 0) {
                cout<<"NO"<<endl;
                continue;
            }
            cout<<"YES"<<endl;
            solve();
        }
    }
    return 0;
}

E. Yurii Can Do Everything

题意:一个数组,然后要找出所以 Good 子串的数量,定义是子串中 左右端点的异或值 等于 子串中所有数的和。

思路:sum(l+1,r−1) ≤ 2⋅max(al,ar),因为异或操作,不可能产生进位。然后设现在 al是最大值。扫描一遍右端点。数出符合条件的个数。 关键在于跳出的条件。因为已经假设了 al是最大值。那么当 sum > al *2 时就跳出循环了。 剩下的会在枚举右端点时枚举到。 让右端点作为最大值。并且可能会枚举到重复的区间。加一个set去重。

AC代码:

#include <bits/stdc++.h>
#define int long long
#define mk make_pair
using namespace std;
const int N = 1e6+7;
const int mod = 1e9+7;
int t,n,m,k;
int a[N];
int sum[N];
 
set<pair<int,int> > st;
 
signed main(){
    int t = 1;
    // cin>>t;
    while(t-- ){
        cin>>n;
        for(int i = 1; i <= n ; i ++){
            cin>>a[i];
            sum[i] = sum[i-1] + a[i];
        }
        for(int i = 1; i <= n ; i ++){
            for(int j = i+2 ; j <= n ; j ++){
                int x = a[i]^a[j];
                int ss = sum[j-1]-sum[i];
                if(ss > a[i]*2) break;
                if(x == ss){
                    st.insert(mk(i,j));
                }
            }
        }
        for(int i = n; i >= 1 ; i --){
            for(int j = i-2 ; j >= 1 ; j --){
                int x = a[i]^a[j];
                int ss = sum[i-1]-sum[j];
                if(ss > a[i]*2) break;
                if(x == ss){
                    st.insert(mk(j,i));
                }
            }
        }
        cout<<st.size()<<endl;
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值