Codeforces Round #731 (Div. 3)

D. Co-growing Sequence

题意:
给定一个数组a,要求输出一个数组b,使a^b得到的数组,ai&ai-1=ai-1。
主要思路:
本题为一个位运算的思维数学题。
经过找规律可得:
a^b&ai-1=ai-1
即 b=~a&ai-1

#include<iostream>
#include<algorithm>
using namespace std;
const int N=2e5+10;
typedef long long ll;
 
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int n;
		cin>>n;
		ll a[N];
		for(int i=0;i<n;i++)
			cin>>a[i];
		cout<<0<<' ';
		for(int i=1;i<n;i++)
		{
			ll ans=a[i-1]&(-a[i]-1);
			//cout<<a[i-1]<<' '<<(-a[i])<<' '<<ans<<endl;
			cout<<ans<<' ';
			a[i]=a[i]^ans;
		}
		cout<<endl;
	}
	return 0;
}

E. Air Conditioners

题意:
一共n个位置,存在k个位置有雪花,离雪花远一格就热一度,输出每个位置的最低温度。
主要思路:
这个问题是一个边界扩散问题,分别从左右两个边界扩散,去最小值即可。
!!!注意初始化的值尽量大

#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
using namespace std;
typedef long long ll;
const int N=3e5+10,maxa=11e9+10;
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int n,k;
		cin>>n>>k;
		ll l[N]={0},r[N]={0},w[N];
                map<ll,ll>v;
		for(int i=0;i<k;i++)
			cin>>w[i];
        for(int i=0;i<=n;i++)
            v[i]=maxa;
 
		for(int j=0;j<k;j++)
        {
            ll x;
            cin>>x;
			v[w[j]]=x;
        }
		ll p=maxa;
		for(int i=0;i<n;i++)
		{
			p=min(p+1,v[i+1]);
			l[i]=p;
		}
		p=maxa;
		for(int i=n-1;i>=0;i--)
		{
			p=min(p+1,v[i+1]);
			r[i]=p;
		}
		for(int i=0;i<n;i++)
		{
			ll ans=min(l[i],r[i]);
			cout<<ans<<' ';
		}
		cout<<endl;
	}
	return 0;
}

F. Array Stabilization (GCD version)

题意:
给定一个数组a,进行ai=gcd(ai,ai+1)的操作,问经过几轮操作后,a中的数相同?
主要思路:
首先将题目进行变形,认真分析可以发现,经过x次操作,即将i处的值a[i]变为gcd(a[i]~a[i+x])。
因为这题给了4s的时间,所以暴力也可以过,推荐二分优化。
暴力:
分别以1-n为起点,计算最少经过多少次,使该位置的数值不再改变(即所有位置的值都相同了)。
二分:
分析可知,最多进行n-1次操作即可将所有元素统一。可以二分mid=(1+n-1)/2。用树状数组或ST表查询各个区间的最大公约数,若相同则r=mid,否则l=mid+1。
(还没学树状数组查询最大公约数,学完补上)

#include<iostream>
#include<algorithm>
using namespace std;
const int N=2e5+10;
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int n;
		int a[N];
		cin>>n;
		for(int i=0;i<n;i++)
			cin>>a[i];
		int ans=0;
		for(int i=0;i<n;i++)
		{
			int sum=0;
			int x=a[i],y=a[(i+1)%n],s=i+1;
			while(x!=y)//还需要进行下一轮
			{
				x=__gcd(x,a[s%n]);
				y=__gcd(y,a[(s+1)%n]);
				s++; 
				sum++;
			} 
			ans=max(ans,sum);
		}
		cout<<ans<<endl;
	}
	return 0;
} 
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=4e5+10;
int f[N][40];
int a[N];
int n;

void init()
{
	int k=floor(log((double)(2*n))/log(2.0));
	for(int j=1;j<=k;j++)
	{
		for(int i = 1; i + (1 << j) - 1 <= n + n; i++)
			f[i][j]=__gcd(f[i][j-1],f[i+(1<<(j-1))][j-1]);
	} 
}

int query(int l,int r)
{
	int k=floor(log((double)(r-l+1))/log(2.0));
	return __gcd(f[l][k],f[r-(1<<k)+1][k]);
}

int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		cin>>n;
        for(int i = 1; i <= n; i++)
            cin >> a[i];
        for(int i = 1; i <= n; i++) a[i + n] = a[i], f[i][0] =f[i + n][0] = a[i]; 
		int g=a[1];
		for(int i=2;i<=n;i++)
			g=__gcd(g,a[i]); 
		init();
		int ans=0;
		for(int i=1;i<=n;i++)
		{
			int l=i,r=i+n-1;
			while(l<r)
			{
				int mid=(l+r)>>1;
				if(query(i,mid)==g)
					r=mid;
				else l=mid+1;
			}
			ans=max(ans,l-i);
		}
		cout<<ans<<endl;
	}
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值