Codeforces Round #736 (Div. 2) (A-D)

时间:2021-08-02
本文章向大家介绍Codeforces Round #736 (Div. 2) (A-D),主要包括Codeforces Round #736 (Div. 2) (A-D)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

A. Gregor and Cryptography

题意:

让你选取两个数使得n取模与这两个数相等 ,保证n是素数并且大于5

分析:

我们知道n是素数并且大于5,那么他一定是个奇数,所以我们直接输出2和n-1即可。

	

B. Gregor and the Pawn Game

题意:

给出你a,b两个数组,然后让你控制b数组的1位置,他可以移动到a数组两种方式:

  • 当b数组i位置是1,如果a数组i位置是0可以一定上面,
  • 当b数组i位置是1,如果a数组(i-1)位置是1可以移动到(i-1)同理可以移动 (i+1)

一个位置最多存放一个,问最多几个?

分析:

直接模拟即可,可以放就放,不可以放就跳过去,三种情况判断,选从i位置是否为0判断,注意标记放1的位置。

ll n;
string str, s;
map<ll, ll>mp;
void solve()
{
    mp.clear();
    cin >> n;
    cin >> str >> s;
    ll sum = 0;
    for(int i = 0; i < n; i++)
    {
        if(s[i] == '1')
        {
            if(mp[i] == 0 && str[i] == '0')
            {
                sum++;
                mp[i] = 1;
            }
            else if(i - 1 >= 0 && mp[i - 1] == 0 && str[i - 1] == '1')
            {
                sum++;
                mp[i - 1] = 1;
            }
            else if(i + 1 < n && mp[i + 1] == 0 && str[i + 1] == '1')
            {
                sum++;
                mp[i + 1] = 1;
            }
        }
    }
    cout << sum << endl;
}

C. Web of Lies

题意:

n个数,m条边,三种操作:

  1. 添加边u和v保证之前没这个边
  2. 删除边u和v保证之前有这个边
  3. 查询,最后剩几个点,原则是如果这个点上没连边就做出贡献, 连着边把点值最小的去除,最后是都是孤点。

分析:

我们计算边上上值小的点,因为删点是从小往大删,如果,这个点连着一个比他大的点,那么它一定会被删掉,所以我们只需要维护没被他大点连接的数量,每次更新只需要维护是否有比他大的数出入。

ll n,m;
string str, s;
map<ll, ll>mp;
void solve()
{
    mp.clear();
    scanf("%lld%lld",&n,&m);
    ll sum=n;
    for(int i=1;i<=m;i++){
    	ll u,v;
    	scanf("%lld%lld",&u,&v);
    	if(u<v) swap(u,v);// u>v;
    	if(mp[v]==0){
    		sum--;    		
    	}
    	mp[v]++;
    }
    ll k;
    cin>>k;
    while(k--){
    	ll op;
    	scanf("%lld",&op);
    	if(op==3){
    		printf("%lld\n",sum);
    	}else if(op==1){
    		ll u,v;
    		scanf("%lld%lld",&u,&v);
    		if(u<v) swap(u,v);// u>v;
	    	if(mp[v]==0){
	    		sum--;    		
	    	}
	    	mp[v]++;
    	}else{
    		ll u,v;
    		scanf("%lld%lld",&u,&v);
    		if(u<v) swap(u,v);// u>v;
	    	if(mp[v]==1){
	    		sum++;    		
	    	}
	    	mp[v]--;
    	}
    }
}

D. Integers Have Friends

题意:

连续一段数对一个数取模之后值相等,对最大长度。

分析:

我们经过对取模后相等,得知,他们的差值一定gcd>1因为只有这样才能取模相等,所以问题就转化成维护区间gcd,找到最长区间gcd>1的长度。 RMQ可以维护,感兴趣可以去学学。

ll gcd(ll a,ll b){
	while(b){
		ll tmp=a%b;
		a=b;
		b=tmp;
	}
	return a;
}
ll a[maxn],b[maxn],n;
ll log_n[maxn];
ll dp[maxn][33];
void LOG(){
	log_n[1]=0;
	for(int i=2;i<=n+1;i++){
		log_n[i]=log_n[i/2]+1;
	}
}
void RMQ(){
	for(int i=1;i<=n;i++){
		dp[i][0]=abs(b[i]);
	}
	for(int j=1;(1<<j)<=n;j++){
		for(int i=1;i+(1<<(j-1))<=n;i++){
			dp[i][j]= gcd(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
		}
	}
}
ll serch(ll l,ll r){
	ll k = log_n[r-l+1];
	return gcd(dp[l][k],dp[r-(1<<k)+1][k]);
}
bool check(ll x){
	if(x==1) return true;
	for(int i=1;i<=n;i++){
		ll j=i+x-1;
		if(j>n) break;
		if(serch(i+1,j)>=2) return true;
	}
	return false;
}
void solve()
{
    scanf("%lld",&n);
    for(int i=1;i<=n;i++){
    	scanf("%lld",&a[i]);
    	b[i]=abs(a[i]-a[i-1]);
    }
    LOG();
    RMQ();
    ll l=1,r=n;
    ll ans=2;
    while(l<=r){
    	ll mid=(l+r)/2;
    	if(check(mid)) {
    		ans=mid;
    		l=mid+1;
    	}
    	else r=mid-1;
    }
    cout<<ans<<endl;
 
 
}

原文地址:https://www.cnblogs.com/KingZhang/p/15089415.html