[Codeforces Round #698 (Div. 2)] A-F题解

[Codeforces Round #698 (Div. 2)] A-F题解
A.Nezzar and Colorful Balls

思路:

贪心,等价求众数的次数

#include<bits/stdc++.h>
#define lson p<<1,l,mid
#define rson p<<1|1,mid+1,r
#define ls p<<1
#define rs p<<1|1
using namespace std;
typedef long long ll;
typedef double db;
int t,n;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0); 
    cin>>t;
    int ans=0,now,a;
    while(t--){ 
        ans=1;
        cin>>n;
        cin>>a;
        now=a;
        int mx=1;
        for(int i=1;i<=n-1;++i){ 
            cin>>a;
            if(now==a)mx++;
            else{ 
                ans=max(ans,mx);
                mx=1;
                now=a;
            }
        }
        ans=max(ans,mx);
        cout<<ans<<"\n";
    }
    return 0;
}

B.Nezzar and Lucky Number

题意:判断给出的数字能否分解为若干个数字之和且这几个数字的数位上存在数字d

思路:个人认为这道题全场最难,其他题都没卡我,就这道题卡了我。若原数字 > = 10 d >=10d >=10d,则可以通过减去10d+1…10d+9,使得最后个位均为d,若 < 10 d <10d <10d,则分解之后只有个位是d,所以直接暴力枚举-10,-20xxxx是否能整除d即可

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <queue>
#include <vector>
#include <set>
#include <bitset>
#include <algorithm>
#define LL long long
#define PII pair<int,int>
#define x first
#define y second
using namespace std;
const int N=2e5+5;
bool check(int x,int d)			//判断x是否合法的函数
{
	if(x>=10*d) return true;	//nd(1<=n<=10)的个位数包含了0-9所有的个位数,因此大于等于10*d的x一定是合法的
	for(int i=1;i*d<=x;i++)				//枚举所有小于等于x的d的倍数
		if(i*d%10==x%10) return true;	//如果有符合条件的则返回true
	return false;
}
int main()
{
    int t;
	scanf("%d",&t);
	while(t--)
	{
		int n,d;
		scanf("%d%d",&n,&d);
		while(n--)
		{
			int x;
			scanf("%d",&x);
			if(check(x,d)) puts("YES");
			else puts("NO");
		}
	}
    return 0;
}
C.Nezzar and Symmetric Array

题意:根据 d i d_i di还原 a i a_i ai

思路:

由于对称,所以一个点x到其他对称点y,-y,要么是2x,要么是2y。所以必须满足以下条件

1.对称

2.%2==0

所以对于最大、次大的 d i d_i di

最大 d i = 2 ∗ m a x ( a i ) ∗ n d_i=2*max(a_i)*n di=2max(ai)n

次大 d i = 2 ∗ 次 大 a i ∗ ( n − 1 ) + 2 ∗ 最 大 a i d_i=2*次大a_i*(n-1)+2*最大a_i di=2ai(n1)+2ai

所以可以O(N)检验推出即可

但是这道题很多坑,首先 a i a_i ai不能重复,其次这样设的话, a i > = 0 a_i>=0 ai>=0

#include<bits/stdc++.h>
#define lson p<<1,l,mid
#define rson p<<1|1,mid+1,r
#define ls p<<1
#define rs p<<1|1
using namespace std;
typedef long long ll;
typedef double db;
const int maxn=2e5+5;
int t,n;
ll d[maxn];//两倍数组
map<ll,int>cnt,cnt2;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0); 
    cin>>t;
    while(t--){
        cnt.clear();
        cnt2.clear();
        cin>>n;
        for(int i=1;i<=2*n;++i)cin>>d[i],cnt[d[i]]++;
        sort(d+1,d+1+2*n);
        bool f=1;
        for(int i=1;i<=2*n;++i){ 
            if(cnt[d[i]]%2!=0||d[i]%2!=0)f=0;
        }
        if(!f){ 
            cout<<"NO"<<"\n";
            continue;
        }
        ll D=d[2*n];
        if(D%(2*n)!=0)f=0;
        ll now=D/(2*n);
        cnt2[now]++;
        ll sum=now;
        for(int i=n-1;i>=1;--i){ 
            if(!f)break;
            ll D=d[2*i];
            if((D-2*sum)%(2*i)!=0)f=0;
            now=(D-2*sum)/(2*i);
            sum+=now;
            if(cnt2[now]==1)f=0;
            cnt2[now]++;
            if(now<=0)f=0;
        }
        cout<<(f?"YES":"NO")<<"\n";
    }
    return 0;
}

D.Nezzar and Board

思路:

煞笔题,容易发现就是x+k1x1…=k是否有解, x i x_i xi就是两两 a i a_i ai的差,显然顺序两两做差可以线性组合出所有的 x i x_i xi,所以 根据裴蜀定理秒了

#include<bits/stdc++.h>
#define lson p<<1,l,mid
#define rson p<<1|1,mid+1,r
#define ls p<<1
#define rs p<<1|1
using namespace std;
typedef long long ll;
typedef double db;
const int maxn=2e5+5;
int t,n;
ll gcd(ll a,ll b){ return b?gcd(b,a%b):a;}
ll a[maxn],k;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0); 
    cin>>t;
    while(t--){ 
        cin>>n>>k;
        for(int i=1;i<=n;++i)cin>>a[i];
        ll G=a[2]-a[1];
        for(int i=3;i<=n;++i)
            G=gcd(G,a[i]-a[i-1]);
        bool flag=0;
        for(int i=1;i<=n;++i){ 
            if((k-a[i])%G==0){ 
                flag=1;break;
            }
        }
        cout<<(flag?"YES":"NO")<<"\n";
    }
    return 0;
}

E.Nezzar and Binary String

题意:

给定初始序列与结果序列,并给出q个查询区间,每次查询后可以将相应的区间内小于一半数量的数进行更改,问是否存在相应的操作满足每次查询到的区间只包含0或1并且最终更改后的初始序列与结果序列相同。

思路:

正着考虑很难做,不知道如何修改,正难则反,反着就变成先考虑是否能够清空,然后再改回满的,最后如果和原序列相同即可,所以对最终序列建立一颗维护区间赋值、区间查询的线段树即可

#include<bits/stdc++.h>
#define lson p<<1,l,mid
#define rson p<<1|1,mid+1,r
#define ls p<<1
#define rs p<<1|1
using namespace std;
const int maxn=2e5+5;
typedef long long ll;
typedef double db;
int t,n,q;
char s1[maxn],s2[maxn];
struct SegmentTree{ 
    int num[maxn<<2],add[maxn<<2];
    void pushUp(int p){ 
        num[p]=num[ls]+num[rs];
    }
    void build(int p,int l,int r){ 
        add[p]=-1;
        if(l==r){ 
            num[p]=(s2[l]=='1');
            return;
        }
        int mid=l+r>>1;
        build(lson);
        build(rson);
        pushUp(p);
    }
    int query(int p,int l,int r,int L,int R){ 
        if(L<=l&&r<=R)return num[p];
        pushDown(p,l,r);
        int mid=l+r>>1,ans=0;
        if(L<=mid)ans+=query(lson,L,R);
        if(R>mid)ans+=query(rson,L,R);
        return ans;
    }
    void pushDown(int p,int l,int r){ 
        if(add[p]==-1)return;
        int mid=l+r>>1;
        num[ls]=(mid-l+1)*add[p];
        num[rs]=(r-mid)*add[p];
        add[ls]=add[rs]=add[p];
        add[p]=-1;
    }
    void update(int p,int l,int r,int L,int R,int val){ 
        if(L<=l&&r<=R){ 
            num[p]=(r-l+1)*val;
            add[p]=val;
            return;
        }
        int mid=l+r>>1;
        pushDown(p,l,r);
        if(L<=mid)update(lson,L,R,val);
        if(R>mid)update(rson,L,R,val);
        pushUp(p);
    }
}tr;
int L[maxn],R[maxn],sum[maxn];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0); 
    cin>>t;
    while(t--){ 
        cin>>n>>q;
        cin>>(s1+1)>>(s2+1);
        for(int i=1;i<=n;++i)sum[i]=sum[i-1]+(s1[i]=='1');
        for(int i=1;i<=q;++i)cin>>L[i]>>R[i];
        tr.build(1,1,n);
        bool is=1;
        for(int i=q;i>=1;--i){ 
            int cnt1=tr.query(1,1,n,L[i],R[i]),cnt2=R[i]-L[i]+1-cnt1;
            if(cnt1==cnt2){ 
                is=0;break;
            }
            tr.update(1,1,n,L[i],R[i],cnt1>cnt2);
        }
        if(!is){ cout<<"NO"<<"\n";continue;}
        for(int i=1;i<=n;++i){ 
            if(sum[i]!=tr.query(1,1,n,1,i)){ 
                is=0;break;
            }
        }
        cout<<(is?"YES":"NO")<<"\n";
    }
    return 0;
}

F.Nezzar and Nice Beatmap

题意:为求出n个点的排列顺序,使得其中任意连续3个点所形成的角都为锐角。

思路:

首先一定存在,如何构造,每次选最远距离的点,由勾股定理必定可解,但是其实还有更方便的写法,就是直接类似冒泡排序,暴力叉积暴力判断,因为最后一定有解,所以一定可以确定下来

另外这题卡精度,不要用double,用ll判断,不然就wa 120

#include<bits/stdc++.h>
#define lson p<<1,l,mid
#define rson p<<1|1,mid+1,r
#define ls p<<1
#define rs p<<1|1
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef double db;
int t,n;
ll dis(ll X1,ll Y1,ll X2,ll Y2){ 
    return (X1-X2)*(X1-X2)+(Y1-Y2)*(Y1-Y2);
}
pair<int,int>P[5050];
int ans[5050],cnt=0;
bool vis[5050];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0); 
    cin>>n;
    for(int i=1;i<=n;++i)cin>>P[i].fi>>P[i].se;
    ans[++cnt]=1;
    vis[1]=1;
    int now=1,nex=1;
    while(cnt<n){ 
        ll mx=0;
        for(int j=1;j<=n;++j){ 
            if(vis[j])continue;
            if(dis(P[now].fi,P[now].se,P[j].fi,P[j].se)>mx){ 
                mx=dis(P[now].fi,P[now].se,P[j].fi,P[j].se);
                nex=j;
            }
        }
        ans[++cnt]=nex;
        vis[nex]=1;
        now=nex;
    }
    for(int i=1;i<=cnt;++i)cout<<ans[i]<<" ";
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值