Codeforces Round #631 (Div. 2)解题报告

题目链接

A.Dreamoon and Ranking Collection

题意:
给 n 个 数 , 是 否 存 在 一 个 1 − v 的 序 列 给n个数,是否存在一个1-v的序列 n1v
其 中 如 果 某 个 数 不 存 在 , 可 以 跳 过 x 次 其中如果某个数不存在,可以跳过x次 x
找 出 最 大 的 v 找出最大的v v
题解:
用 数 组 存 一 下 每 个 数 的 个 数 用数组存一下每个数的个数
从 1 − 200 循 环 , 如 果 数 存 在 就 下 一 个 , 不 存 在 就 跳 过 从1-200循环,如果数存在就下一个,不存在就跳过 1200
直 到 x = = 0   & &   当 前 数 不 存 在 直到x==0~\&\&~当前数不存在 x==0 && 

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}};

int a[210],b[210];

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,x,ans=0;
        cin>>n>>x;
        memset(b,0,sizeof b);
        for(int i=1;i<=n;i++)cin>>a[i],b[a[i]]=1;
        for(int i=1;i<=200;i++){
            if(!b[i]&&!x)break;
            if(!b[i])x--;
            ans=i;
        }
        cout<<ans<<endl;
    }
}


B.Dreamoon Likes Permutations

题意:
给 一 个 长 度 为 n 的 数 组 给一个长度为n的数组 n
是 否 能 分 成 左 右 两 部 分 , 使 得 每 部 分 成 为 一 个 序 列 是否能分成左右两部分,使得每部分成为一个序列 使
即 包 含 1 − x 的 所 有 数 即包含1-x的所有数 1x
题解:
直 接 计 算 前 缀 和 和 后 缀 和 直接计算前缀和和后缀和
用 一 个 m a p 存 一 下 是 否 出 现 重 复 元 素 , 出 现 就 b r e a k 用一个map存一下是否出现重复元素,出现就break mapbreak
否 则 用 高 斯 公 式 算 如 果 前 缀 和 和 后 缀 和 都 满 足 则 记 录 答 案 否则用高斯公式算 如果前缀和和后缀和都满足则记录答案

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}};

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 t;
    cin>>t;
    while(t--){
        int n;
        vector<int> ans;
        map<int,int> m1,m2;
		cin>>n;
		int num=0;
		ll pre=0,sum=0;
		for(int i=1;i<=n;i++) cin>>a[i],sum+=a[i],m2[a[i]]++;
		for(ll i=1;i<n;i++){
			pre+=a[i];
			m1[a[i]]++;
			if(m1[a[i]]>1) break;
			m2[a[i]]--;
			if(m2[a[i]]==0) m2.erase(a[i]);
			if(m1.size()+m2.size()==n&&pre==(1+i)*i/2&&(sum-pre)==(1+n-i)*(n-i)/2) ans.pb(i),num++;
		}
		cout<<ans.size()<<endl;
		for(auto i:ans){
			cout<<i<<' '<<n-i<<endl;
		}
    }
}


C.Dreamoon Likes Coloring

题意:
n 个 点 , 涂 色 m 次 , 每 次 涂 的 长 度 为 L i , 颜 色 为 i n个点,涂色m次,每次涂的长度为L_i,颜色为i nmLii
你 选 定 的 涂 色 位 置 必 须 保 证 整 个 长 度 都 能 够 涂 上 该 颜 色 你选定的涂色位置必须保证整个长度都能够涂上该颜色
每 个 点 的 颜 色 取 决 于 最 后 一 次 涂 的 颜 色 每个点的颜色取决于最后一次涂的颜色
确 保 每 个 颜 色 都 存 在 并 且 每 个 点 都 有 颜 色 确保每个颜色都存在并且每个点都有颜色
题解:
特 判 一 下 颜 色 不 覆 盖 , 如 果 不 够 n 个 点 , 输 出 − 1 特判一下颜色不覆盖,如果不够n个点,输出-1 n1
然 后 如 果 还 没 涂 的 长 度 能 够 大 于 没 涂 的 点 , 就 在 上 次 涂 后 的 下 一 个 点 涂 然后如果还没涂的长度能够大于没涂的点,就在上次涂后的下一个点涂
如 果 这 样 涂 超 出 了 n 个 点 , 就 输 出 − 1 如果这样涂超出了n个点,就输出-1 n1
如 果 剩 余 还 没 涂 的 长 度 小 于 剩 下 的 点 , 就 在 n − s u m i + 1 位 置 开 始 涂 如果剩余还没涂的长度小于剩下的点,就在n-sum_i+1位置开始涂 nsumi+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 l[maxn],sum[maxn],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,m;
    cin>>n>>m;
    for(int i=1;i<=m;i++)cin>>l[i];
    for(int i=m;i;--i)
        sum[i]=sum[i+1]+l[i];
    if(sum[1]<n){cout<<-1;return 0;}
    ans[1]=1;
    for(int i=2;i<=m;++i)
        ans[i]=max(ans[i-1]+1,n-sum[i]+1);
    for(int i=1;i<=m;++i)if(ans[i]+l[i]-1>n){cout<<-1;return 0;}
    for(int i=1;i<=m;++i)
        cout<<ans[i]<<' ';
    return 0;
}


D.Dreamoon Likes Sequences

题意:
给 一 个 数 d 和 m , m 是 模 数 , 最 后 答 案 向 m 取 余 给一个数d和m,m是模数,最后答案向m取余 dmmm
让 你 构 造 一 个 数 组 1 < = a 1 < a 2 < . . . . a n < = d 让你构造一个数组1<=a_1<a_2<....a_n<=d 1<=a1<a2<....an<=d
必 须 存 在 数 组 b 是 a 的 异 或 前 缀 , 保 证 b 也 是 严 格 升 序 必须存在数组b是a的异或前缀,保证b也是严格升序 bab
题解
可 以 看 出 , 如 果 b 也 是 严 格 升 序 的 话 可以看出,如果b也是严格升序的话 b
必 须 让 a 的 每 一 位 数 的 二 进 制 最 高 位 大 于 前 一 位 的 最 高 位 必须让a的每一位数的二进制最高位大于前一位的最高位 a
所 以 就 对 每 一 二 进 制 位 循 环 所以就对每一二进制位循环
i 从 0 开 始 , 假 设 最 高 位 是 1 < < i , 存 在 2 i 种 数 i从0开始,假设最高位是1<<i,存在2^i种数 i01<<i2i
所 以 每 次 用 前 面 的 所 有 情 况 乘 这 个 数 的 种 类 数 所以每次用前面的所有情况乘这个数的种类数
并 且 加 上 这 个 数 单 独 存 在 的 情 况 , 然 后 加 上 前 面 所 有 出 现 的 情 况 并且加上这个数单独存在的情况,然后加上前面所有出现的情况
这 样 就 构 造 出 了 一 个 O ( l o g 2 d ) 复 杂 度 的 d p 操 作 这样就构造出了一个O(log_2d)复杂度的dp操作 O(log2d)dp
由 于 每 次 操 作 只 和 前 一 个 有 关 , 所 以 只 用 一 个 数 一 直 维 护 就 可 以 由于每次操作只和前一个有关,所以只用一个数一直维护就可以

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}};



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--){
        ll d,m;
        cin>>d>>m;
        ll ans=0;
        for(int i=0;(1ll<<i)<=d;i++){
            int s=0;
            if((1ll<<(i+1))<=d)s=1<<i;
            else s=d-(1<<i)+1;
            ans=(ans+s*ans%m+s)%m;
        }
        cout<<ans<<endl;
    }

    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值