Codeforces Round #825 (Div. 2) BC1D

B. Playing with GCD

题意:给定一个长度为 n n n 的数组 a a a,判断是否存在一个数组 b b b (长度为 n + 1 n+1 n+1),使得对于 a i a_i ai 的每一项都有 a i = g c d ( b i , b i + 1 ) a_i=gcd(b_i,b_{i+1}) ai=gcd(bi,bi+1)
思路1:参考。因为 a i − 1 = g c d ( b i − 1 , b i ) a_{i-1}=gcd(b_{i-1},b_{i}) ai1=gcd(bi1,bi), a i + 1 = g c d ( b i + 1 , b i + 2 ) a_{i+1}=gcd(b_{i+1},b_{i+2}) ai+1=gcd(bi+1,bi+2),且, a i = g c d ( b i , b i + 1 ) a_{i}=gcd(b_{i},b_{i+1}) ai=gcd(bi,bi+1),因此, a i a_{i} ai 要能被 g c d ( a i − 1 , a i + 1 ) gcd(a_{i-1},a_{i+1}) gcd(ai1,ai+1) 整除。
思路2:构造 b b b 数组, b 1 = a 1 , b n + 1 = a n b_1=a_1, b_{n+1}=a_n b1=a1,bn+1=an,其他位置的 b i = l c m ( a i − 1 , a i ) b_i=lcm(a_{i-1},a_{i}) bi=lcm(ai1,ai)。判断该 b b b 数组是否能还原 a a a 数组。证明可以看一下官方题解。
思路1代码:

#include <bits/stdc++.h>
using namespace std;
 
#define int long long
const int N=1e5+5; 
int T,n,a[N];
 
signed main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	cin>>T;
	while(T--){
		cin>>n;
		for(int i=1;i<=n;++i) cin>>a[i];
		string ans="YES\n";
		for(int i=2;i<n;++i){
			if(a[i]%(__gcd(a[i-1],a[i+1]))) ans="NO\n";
		}
		cout<<ans;
	}
} 

C1. Good Subarrays (Easy Version)

题意:给定一个长度为 n n n 的数组 a a a,求有多少对 ( l , r ) , 1 ≤ l ≤ r ≤ n (l,r),1\le l\le r\le n (l,r),1lrn 是好的。 ( l , r ) (l,r) (l,r) 表示了 a l . . . a r a_l...a_r al...ar 这段元素。定义长度为 m m m 的一段序列 b b b 是好的,当且仅当,对于每一个 i i i, 1 ≤ i ≤ m 1\le i \le m 1im, b i ≥ i b_i \ge i bii
思路:遍历数组,判断当前位置是否可以作为第 ( l e n + 1 ) (len+1) (len+1)位,若能,则继续向下遍历,直到某位置上的数不能作为第 ( l e n + 1 ) (len+1) (len+1)位,累积长度为 l e n len len的序列对答案的贡献为 l e n ∗ ( l e n + 1 ) / 2 len*(len+1)/2 len(len+1)/2 ,然后更新 l e n len len,去找出下一段合法序列,注意,该位置的左边界不一定是该位置,可能更左一些。
代码:

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N=2e5+5;

int T,n,a[N],b[N];

signed main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	cin>>T;
//	T=1;
	while(T--){
		cin>>n;
		for(int i=1;i<=n;++i) cin>>a[i];
		a[n+1]=0;
		if(n==1) cout<<1<<'\n';
		else{
			int len=1,ans=0;
			for(int i=2;i<=n+1;++i){
				if(a[i]>len) len++;
				else{
					ans+=(len*(len+1)/2);
					len=min(len,min(i,a[i]));
					ans-=(len*(len-1)/2);
				}
			}
			cout<<ans<<'\n';	
		}
	}
}

D. Equal Binary Subsequences

个人觉得这是一道很棒的题!!!
题意:给定一个长度为 2 n 2n 2n 的字符串。要求选一个子序列,操作一次 右循环一个单位。然后判断是否能将串分成两个长度为 n n n 的,完全一样的子序列,若不能,输出-1;若能输出选择循环的子序列大小和元素下标,以及其中一个长度为 n n n的子序列的下标。
思路:官方题解讲得超好!建议看看官方题解。
代码:

#include <bits/stdc++.h>
using namespace std;

#define int long long
#define pb push_back
int T,n;
string s;

signed main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	cin>>T;
	while(T--){
		cin>>n>>s;
		int cnt=0;
		for(int i=0;i<s.size();++i) if(s[i]=='1') cnt++;
		if(cnt%2) cout<<-1<<'\n';
		else{
			vector<int> v;
			for(int i=0;i<s.size();i+=2){
				if(s[i]!=s[i+1]){
					if(v.size()%2==0) { //取0的下标 
						if(s[i]=='0') v.pb(i);
						else v.pb(i+1);
					}
					else { //取1的下标 
						if(s[i]=='1') v.pb(i);
						else v.pb(i+1);
					}
				}
			}
			cout<<v.size();
			for(auto x:v) cout<<' '<<x+1;
			cout<<'\n';
			for(int i=0;i<s.size();i+=2) cout<<i+1<<' ';
			cout<<'\n';	
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值