Codeforces Round #696 (Div. 2)ABCD——解题报告

比赛链接

Link

A - Puzzle From the Future

题解

本来以为是个规律题,还找了一个看似合理的规律,最后发现直接模拟就行了。
根据题意进行贪心模拟就行了,
当前位置为1时,看上一个位置的和是不是2,是的话当前位置只能为0,否则就选1
当前位置为0时,看上一个位置的和是不是1,是的话当前位置只能为0,否则就选1

代码

#include <bits/stdc++.h>
#define PI atan(1.0)*4
#define rp(i,s,t) for (register int i = (s); i <= (t); i++)
#define RP(i,t,s) for (register int i = (t); i >= (s); i--)
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define ll long long
#define ull unsigned long long
#define mst(a,b) memset(a,b,sizeof(a))
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define m_p make_pair
#define p_b push_back
#define ins insert
#define era erase
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
#define dg if(debug)
#define outval(a) cout << "Debuging...|" << #a << ": " << a << "\n";
using namespace std;
int debug = 0;
ll gcd(ll a,ll b){
	return b?gcd(b,a%b):a;
}
ll lcm(ll a,ll b){
	return a/gcd(a,b)*b;
}
inline int read(){
	int s=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		s=s*10+ch-'0';
		ch=getchar();
	}
	return s*f;
}
const int N = 1e5+7;
int a[N];
void solve(){
	int n=read();
	string s;cin>>s;
	int pre=-1;
	rp(i,0,n-1){
		if(s[i]=='1'){
			if(pre!=2) printf("1"),pre=2;
			else printf("0"),pre=1;
		}
		else{
			if(pre==1) printf("0"),pre=0;
			else printf("1"),pre=1;
		}
	}
	puts("");
}
int main(){
	//ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#ifdef ONLINE_JUDGE
#else
	freopen("in.txt", "r", stdin);
	//debug = 1;
#endif
	//time_t beg, end;
	//if(debug) beg = clock();

	int T=read();
	while(T--) solve();

	/*
	if(debug) {
		end = clock();
		printf("time:%.2fs\n", 1.0 * (end - beg) / CLOCKS_PER_SEC);
	}
	*/
	return 0;
}

B - Different Divisor

题解

先用线性筛筛出1~100007的所有质数(范围尽量大)
然后直接选择第一个大于等于d+1的质数a作为一个约数
另一个约数就是第一个大于等于a+d的质数b。
答案就是这个质数的乘积(a*b)。
至于证明可以参考官方题解

代码

#include <bits/stdc++.h>
#define PI atan(1.0)*4
#define rp(i,s,t) for (register int i = (s); i <= (t); i++)
#define RP(i,t,s) for (register int i = (t); i >= (s); i--)
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define ll long long
#define ull unsigned long long
#define mst(a,b) memset(a,b,sizeof(a))
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define m_p make_pair
#define p_b push_back
#define ins insert
#define era erase
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
#define dg if(debug)
#define outval(a) cout << "Debuging...|" << #a << ": " << a << "\n";
using namespace std;
int debug = 0;
ll gcd(ll a,ll b){
	return b?gcd(b,a%b):a;
}
ll lcm(ll a,ll b){
	return a/gcd(a,b)*b;
}
inline int read(){
	int s=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		s=s*10+ch-'0';
		ch=getchar();
	}
	return s*f;
}
const int N = 1e5+7;
int a[N];
struct Prime {
	vector<int> arr;
	int vis[1000006];
	void doit(int maxnum) {
		for(int i = 2; i <= maxnum; ++i) {
			if(!vis[i]) arr.push_back(i);
			for(int j = 0; j < arr.size() && arr[j] * i <= maxnum; ++j) {
				vis[arr[j] * i] = 1;
				if(i % arr[j] == 0) break;
			}
		}
	}
}P;
void solve(){
	int d=read();
    int a = *lower_bound(P.arr.begin(), P.arr.end(), d + 1);
    int b = *lower_bound(P.arr.begin(), P.arr.end(), a + d);
    printf("%lld\n", 1ll*a * b);
}
int main(){
	//ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#ifdef ONLINE_JUDGE
#else
	freopen("in.txt", "r", stdin);
	//debug = 1;
#endif
	//time_t beg, end;
	//if(debug) beg = clock();
	P.doit(1000007);
	int T=read();
	while(T--) solve();

	/*
	if(debug) {
		end = clock();
		printf("time:%.2fs\n", 1.0 * (end - beg) / CLOCKS_PER_SEC);
	}
	*/
	return 0;
}

C - Array Destruction

题解

这个题的关键在于要知道第一步肯定是选择最大值和数组中的一个数,而当这个数确定后,剩下也就可以递推地进行维护,因为我们每次都要取剩下可选的数中最大的数作为其中一个数,另一个数就可以通过上一次的数减去当前选的那个数确定。
因此我们可以首先枚举一下和最大值匹配的那个数,然后判断是否存在合法的操作顺序就行了。
注意这个题会卡常,因此怎么维护每次选取可选数中最大的那个数的方法很关键。
比较好的方法是用multiset或者map维护。

代码

#include <bits/stdc++.h>
#define PI atan(1.0)*4
#define rp(i,s,t) for (register int i = (s); i <= (t); i++)
#define RP(i,t,s) for (register int i = (t); i >= (s); i--)
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define ll long long
#define ull unsigned long long
#define mst(a,b) memset(a,b,sizeof(a))
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define m_p make_pair
#define p_b push_back
#define ins insert
#define era erase
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
#define dg if(debug)
#define outval(a) cout << "Debuging...|" << #a << ": " << a << "\n";
using namespace std;
int debug = 0;
ll gcd(ll a,ll b){
	return b?gcd(b,a%b):a;
}
ll lcm(ll a,ll b){
	return a/gcd(a,b)*b;
}
inline int read(){
	int s=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		s=s*10+ch-'0';
		ch=getchar();
	}
	return s*f;
}
const int N = 2e4+7;
int a[N];
map<int,int> mp;
vector<pii> v;
void solve(){
	int n=read();
	rp(i,1,n*2) a[i]=read();
	sort(a+1,a+1+n*2);
	mp.clear();
	rp(i,1,n*2) mp[a[i]]++;
	rp(i,1,n*2-1){
		int f=1;
		v.clear();
		v.p_b(m_p(a[i],a[2*n]));
		mp[a[i]]--;
		mp[a[2*n]]--;
		int cur=a[2*n];
		// outval(a[i]);
		// for(auto val:mp){
		// 	cout<<val.first<<" "<<val.second<<endl;
		// }
		RP(j,2*n,1){
			if(mp.find(a[j])==mp.end()||mp[a[j]]==0) continue;
			if(mp.find(cur-a[j])!=mp.end()&&mp[cur-a[j]]>0){
				if(cur-a[j]==a[j]){
					if(mp[cur-a[j]]>=2){	
						mp[cur-a[j]]--;
						mp[a[j]]--;
						v.p_b(m_p(a[j],cur-a[j]));
					}
					else {
						f=0;
						break;
					}
				}
				else{
					mp[cur-a[j]]--;
					mp[a[j]]--;
					v.p_b(m_p(a[j],cur-a[j]));
				}
			}
			else{
				f=0;
				break;
			}
			// if(a[i]==4){
				// cout<<a[j]<<" "<<cur<<endl;
			// }
			cur=a[j];
		}
		// cout<<a[i]<<" "<<f<<endl;
		if(f){
			puts("YES");
			printf("%d\n",v[0].first+v[0].second);
			for(auto val:v) printf("%d %d\n",val.first,val.second);
			return ;
		}
		else{
			for(auto val:v){
				mp[val.first]++;
				mp[val.second]++;
			}
		}
	}
	puts("NO");
}
int main(){
	//ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#ifdef ONLINE_JUDGE
#else
	freopen("in.txt", "r", stdin);
	// debug = 1;
#endif
	time_t beg, end;
	if(debug) beg = clock();

	int T=read();
	while(T--) solve();

	if(debug) {
		end = clock();
		printf("time:%.2fs\n", 1.0 * (end - beg) / CLOCKS_PER_SEC);
	}
	return 0;
}

D - Cleaning

题解

首先可以知道我们要么从开头从前往后开始消,要么从结尾从后往前开始消。
消除的过程就是用当前数减去前面一个被消除后剩下的数(从前往后消)。
如果(当前数)比(前面的被消除后的数)小时,这时就代表不合法的情况。
从后往前消的过程类似。
而对于交换两个数a[i]和a[i+1],既不会对a[i]之前的数有影响,也不会对a[i+1]后面的数有影响。
因此解法就出来了,我们可以枚举交换的两个数的位置i和i+1。
然后判断 a[i+1] -(i之前的数通过从前往后的消除剩下的结果pre[i-1])
是否等于 a[i] - (i+1之后的数通过从后往前的消除剩下的结果suf[i+2])。
注意一下还需要判断pre[i-1]和suf[i+2]是否合法。
详细过程和分析参考关于D题的分析过程

代码

#include <bits/stdc++.h>
#define PI atan(1.0)*4
#define rp(i,s,t) for (register int i = (s); i <= (t); i++)
#define RP(i,t,s) for (register int i = (t); i >= (s); i--)
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define ll long long
#define ull unsigned long long
#define mst(a,b) memset(a,b,sizeof(a))
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define m_p make_pair
#define p_b push_back
#define ins insert
#define era erase
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
#define dg if(debug)
#define outval(a) cout << "Debuging...|" << #a << ": " << a << "\n";
using namespace std;
int debug = 0;
ll gcd(ll a,ll b){
	return b?gcd(b,a%b):a;
}
ll lcm(ll a,ll b){
	return a/gcd(a,b)*b;
}
inline int read(){
	int s=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		s=s*10+ch-'0';
		ch=getchar();
	}
	return s*f;
}
const int N = 2e5+17;
int a[N],pre[N],suf[N];
void solve(){
	int n=read();
	rp(i,1,n) a[i]=read();
	rp(i,0,n+10) pre[i]=suf[i]=0;
	rp(i,1,n){
		if(pre[i-1]==-1) pre[i]=-1;
		else {
			if(a[i]-pre[i-1]<0) pre[i]=-1;
			else pre[i]=a[i]-pre[i-1];
		}
	}
	if(pre[n]==0){
		puts("YES");
		return ;
	}
	RP(i,n,1){
		if(suf[i+1]==-1) suf[i]=-1;
		else {
			if(a[i]-suf[i+1]<0) suf[i]=-1;
			else suf[i]=a[i]-suf[i+1];
		}
	}
	rp(i,1,n-1){
		if(pre[i-1]==-1||suf[i+2]==-1) continue;
		if(a[i+1]>=pre[i-1]&&a[i]>=suf[i+2]&&a[i+1]-pre[i-1]==a[i]-suf[i+2]){
			puts("YES");
			return ;
		}
	}
	puts("NO");
}
int main(){
	//ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#ifdef ONLINE_JUDGE
#else
	freopen("in.txt", "r", stdin);
	//debug = 1;
#endif
	//time_t beg, end;
	//if(debug) beg = clock();

	int T=read();
	while(T--) solve();

	/*
	if(debug) {
		end = clock();
		printf("time:%.2fs\n", 1.0 * (end - beg) / CLOCKS_PER_SEC);
	}
	*/
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值