Codeforces Round #632 (Div. 2)题解

题目链接

A.Little Artem

题意:
n ∗ m 的 网 格 中 , 有 黑 白 两 种 颜 色 n*m的网格中,有黑白两种颜色 nm
B 是 相 邻 了 白 色 的 黑 格 数 量 B是相邻了白色的黑格数量 B
W 是 相 邻 了 黑 色 的 白 格 数 量 W是相邻了黑色的白格数量 W
构 造 一 个 n ∗ m 的 图 , 保 证 B = W + 1 构造一个n*m的图,保证B=W+1 nmB=W+1
题解:
因 为 B = W + 1 , 所 以 让 黑 白 有 x 个 相 邻 的 因为B=W+1,所以让黑白有x个相邻的 B=W+1x
然 后 由 于 黑 色 的 比 白 色 多 , 让 两 个 黑 色 的 相 邻 一 个 公 共 的 然后由于黑色的比白色多,让两个黑色的相邻一个公共的
所 以 就 可 以 构 造 出 , 第 一 列 和 第 n 行 全 是 B , 其 他 是 W 所以就可以构造出,第一列和第n行全是B,其他是W nBW
这 样 , 每 个 黑 色 对 应 一 个 白 色 这样,每个黑色对应一个白色
但 是 第 一 列 第 n − 1 行 的 和 第 n 行 第 2 列 的 公 用 一 个 白 色 但是第一列第n-1行的和第n行第2列的公用一个白色 n1n2
所 以 白 色 的 少 一 个 , 保 证 了 B = W + 1 所以白色的少一个,保证了B=W+1 B=W+1

AC代码

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e5+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};




int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int t;
    cin>>t;
    while(t--){
        int n,m;
        cin>>n>>m;
        for(int i=1;i<n;i++,cout<<endl)
            for(int j=1;j<=m;j++)
                if(j==1)cout<<'B';
                else cout<<'W';
        for(int i=1;i<=m;i++)
            cout<<'B';
        cout<<endl;
    }
    return 0;
}


B.Kind Anton

题意:
给 定 一 个 长 度 为 n 的 数 组 a 和 数 组 b 给定一个长度为n的数组a和数组b nab
a 的 每 个 元 素 由 { 0 , 1 , − 1 } 组 成 a的每个元素由\{0,1,-1\}组成 a{0,1,1}
可 以 进 行 一 个 操 作 任 意 次 : 可以进行一个操作任意次:
对 于 i < j , a j + = a i 对于i<j,a_j+=a_i i<jaj+=ai
问 a 是 否 能 够 等 于 b 问a是否能够等于b ab
题解:
由 于 只 有 前 面 的 数 给 后 面 的 数 赋 值 由于只有前面的数给后面的数赋值
所 以 用 m a p 或 者 数 组 维 护 已 经 出 现 过 的 1 或 者 − 1 所以用map或者数组维护已经出现过的1或者-1 map11
所 以 只 需 要 看 如 果 a i ! = b i     a i 变 成 b i 需 要 1 还 是 − 1 所以只需要看如果a_i!=b_i~~~a_i变成b_i需要1还是-1 ai!=bi   aibi11
如 果 对 于 所 有 i 需 要 的 都 存 在 那 么 就 能 够 等 于 数 组 b 如果对于所有i需要的都存在那么就能够等于数组b ib

AC代码

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e5+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};


int a[maxn],b[maxn];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        map<int,int> m;
        for(int i=1;i<=n;i++)cin>>a[i];
        for(int i=1;i<=n;i++)cin>>b[i];
        bool f=0;
        for(int i=1;i<=n;i++){
            if(a[i]==b[i]){m[a[i]]++;continue;}
            int d=b[i]-a[i];
            if(d>0&&m[1]){m[a[i]]++;continue;}
            if(d<0&&m[-1]){m[a[i]]++;continue;}
            f=1;m[a[i]]++;
        }
        if(f)cout<<"NO"<<endl;
        else cout<<"YES"<<endl;
    }
    return 0;
}


C.Eugene and an array

题意:
给 一 个 长 度 为 n 的 数 组 给一个长度为n的数组 n
问 能 找 到 多 少 个 子 段 , 这 个 子 段 的 任 意 子 段 和 不 为 0 问能找到多少个子段,这个子段的任意子段和不为0 0
题解:
对 于 每 个 位 置 的 值 , 看 它 能 和 它 前 面 的 多 少 位 可 以 组 成 符 合 条 件 的 子 段 对于每个位置的值,看它能和它前面的多少位可以组成符合条件的子段
所 以 要 用 m a p 维 护 已 经 枚 举 过 的 前 缀 和 的 最 后 一 次 出 现 位 置 所以要用map维护已经枚举过的前缀和的最后一次出现位置 map
然 后 如 果 某 个 前 缀 和 出 现 过 , 说 明 这 次 和 m a p 维 护 的 位 置 之 间 和 是 0 然后如果某个前缀和出现过,说明这次和map维护的位置之间和是0 map0
所 以 只 能 从 m a p 的 位 置 的 下 一 个 开 始 到 这 个 点 的 子 段 符 合 所以只能从map的位置的下一个开始到这个点的子段符合 map
由 于 子 段 和 不 能 为 0 , 所 以 这 一 段 也 不 能 出 现 在 后 面 的 子 段 中 由于子段和不能为0,所以这一段也不能出现在后面的子段中 0
所 以 每 次 更 新 一 个 能 取 到 最 左 值 l , 就 是 每 次 m a p 位 置 的 后 一 个 位 置 所以每次更新一个能取到最左值l,就是每次map位置的后一个位置 lmap
如 果 a i 为 0 , 那 说 明 1 到 i 的 所 有 都 不 能 和 i 后 面 的 形 成 符 合 条 件 的 子 段 如果a_i为0,那说明1到i的所有都不能和i后面的形成符合条件的子段 ai01ii
所 以 直 接 更 新 最 左 值 l = i + 1 所以直接更新最左值l=i+1 l=i+1
对 于 每 次 位 置 的 更 新 , 答 案 也 加 上 能 取 到 的 结 果 对于每次位置的更新,答案也加上能取到的结果

AC代码

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=2e5+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};


ll a[maxn],sum[maxn];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i],sum[i]=sum[i-1]+a[i];
    map<ll,int> m;
    int l=0;
    ll ans=0;
    for(ll i=1;i<=n;i++){
        if(!m[sum[i]]&&sum[i]&&a[i])ans+=(i-l);
        else if(!a[i])l=i;
        else l=max(l,m[sum[i]]+1),ans+=(i-l);
        m[sum[i]]=i;
    }
    cout<<ans;
    return 0;
}


D.Challenges in school №41

题意:
一 个 队 列 有 n 个 人 , 每 个 人 站 的 方 向 可 能 是 L 或 R 一个队列有n个人,每个人站的方向可能是L或R nLR
可 能 两 个 人 会 有 面 对 面 的 情 况 可能两个人会有面对面的情况
你 每 次 至 少 使 一 对 面 对 面 的 人 同 时 转 身 你每次至少使一对面对面的人同时转身 使
是 否 你 能 够 在 k 次 使 得 这 个 队 列 没 有 面 对 面 的 人 是否你能够在k次使得这个队列没有面对面的人 k使
如 果 可 以 输 出 这 k 次 翻 转 的 人 如果可以输出这k次翻转的人 k
题解:
由 于 你 想 让 所 有 面 对 面 的 人 都 不 面 对 面 由于你想让所有面对面的人都不面对面
只 有 每 次 让 他 们 转 身 只有每次让他们转身
所 以 只 有 暴 力 模 拟 , 直 到 不 出 现 面 对 面 , 每 次 记 录 所以只有暴力模拟,直到不出现面对面,每次记录
由 于 每 次 至 少 翻 转 一 对 , 所 以 可 以 同 时 翻 转 多 对 面 对 面 的 人 由于每次至少翻转一对,所以可以同时翻转多对面对面的人
为 了 使 答 案 最 小 化 , 每 次 翻 转 所 有 面 对 面 的 人 为了使答案最小化,每次翻转所有面对面的人 使
如 果 这 样 翻 转 还 是 需 要 比 k 次 数 多 , 说 明 不 可 能 完 成 如果这样翻转还是需要比k次数多,说明不可能完成 k
然 而 , 你 可 以 每 次 只 翻 转 一 对 , 可 以 达 到 将 一 次 翻 转 分 成 多 次 的 效 果 然而,你可以每次只翻转一对,可以达到将一次翻转分成多次的效果
但 是 , 如 果 按 这 样 全 部 分 开 , 还 是 比 k 小 , 那 就 说 明 不 能 完 成 但是,如果按这样全部分开,还是比k小,那就说明不能完成 k
然 后 , 就 是 按 这 样 , 把 所 有 的 次 数 转 化 成 k 次 完 成 即 可 然后,就是按这样,把所有的次数转化成k次完成即可 k

AC代码

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=3e6+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};

vector<int> v[100010];
vector<int> ans[maxn];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int n,k;
    cin>>n>>k;
    string s;
    cin>>s;
    int cnt=0,tot=0;
    while(1){
        cnt++;
        bool f=0;
        for(int i=0;i<n;i++)
            if(s[i]=='R'&&s[i+1]=='L')
                v[cnt].pb(i+1),swap(s[i],s[i+1]),f=1,tot++,i++;
        if(!f)break;
        if(cnt>k){cout<<-1;return 0;}
    }
    if(k>tot){cout<<-1;return 0;}
    int c=0;
    for(int i=1;i<cnt;i++){
        for(auto j:v[i]){
            if(cnt-i<k)ans[c++].pb(j),k--;
            else ans[c].pb(j);
        }
        if(cnt-i>=k&&!ans[c].empty())c++,k--;
    }
    for(int i=0;i<c;i++){
            cout<<(int)ans[i].size()<<' ';
            for(auto j:ans[i])cout<<j<<' ';
            cout<<endl;
    }
    return 0;
}


F.Kate and imperfection

题意:
给 一 个 数 n 给一个数n n
让 你 从 1 − n 中 每 次 找 出 x 个 数 ( 2 < = x < = n ) 为 集 合 s 让你从1-n中每次找出x个数(2<=x<=n)为集合s 1nx(2<=x<=n)s
F ( s ) 表 示 x 个 数 中 任 意 两 个 数 a , b 的 g c d ( a , b ) 的 最 大 值 F(s)表示x个数中任意两个数a,b的gcd(a,b)的最大值 F(s)xabgcd(a,b)
让 你 使 这 个 对 于 2 < = x < = n 使 得 F ( s ) 最 小 让你使这个对于2<=x<=n使得F(s)最小 使2<=x<=n使F(s)
对 于 x 从 2 − n 求 出 这 个 最 小 的 F ( s ) 对于x从2-n求出这个最小的F(s) x2nF(s)
题解:
首 先 自 己 手 写 枚 举 一 下 , 可 以 发 现 首先自己手写枚举一下,可以发现
每 次 先 把 质 数 找 齐 , 肯 定 这 些 值 都 是 1 每次先把质数找齐,肯定这些值都是1 1
然 后 再 找 2 , 4 , 6 , 9 , 8 , 10 这 样 的 顺 序 然后再找2,4,6,9,8,10这样的顺序 2469810
而 且 F ( s ) 是 随 x 递 增 的 而且F(s)是随x递增的 F(s)x
这 样 会 发 现 , 如 果 一 个 数 不 是 质 数 , 你 又 必 须 选 到 这 个 数 这样会发现,如果一个数不是质数,你又必须选到这个数
那 么 F ( s ) 就 是 这 个 数 的 最 大 因 子 那么F(s)就是这个数的最大因子 F(s)
所 以 问 题 转 化 成 了 , 找 每 个 数 的 最 大 因 子 , 统 计 到 一 起 所以问题转化成了,找每个数的最大因子,统计到一起
然 后 从 小 到 大 输 出 就 可 以 了 然后从小到大输出就可以了
这 里 就 可 以 用 类 似 素 数 筛 的 方 法 进 行 预 处 理 这里就可以用类似素数筛的方法进行预处理
然 后 找 到 每 个 数 的 最 大 因 子 , 再 用 v e c t o r 读 取 一 遍 排 个 序 然后找到每个数的最大因子,再用vector读取一遍排个序 vector

AC代码

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=5e5+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};

int a[maxn];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int n;
    cin>>n;
    for(int i=2;i<=n;i++)
        if(!a[i])
        for(int j=i;j<=n;j+=i)
            if(!a[j])a[j]=j/i;
    a[1]=1;
    vector<int> v;
    for(int i=1;i<=n;i++)
        if(a[i])v.pb(a[i]);
    sort(all(v));
    for(int i=1;i<n;i++)
        cout<<v[i]<<' ';
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值