CF999

A

link

首先,每次操作(第一次除外)之前\(s\)一定是一个奇数,那么我们要再加一个奇数才能让它变为偶数分数加一。
那么就是说操作过至少一次后,有几个奇数就有几分。
那么如果有至少一个偶数,那么第一次用偶数可以得分,后面再用奇数可以得分,偶数的不了分,最终得分就是奇数个数加一,如果没有偶数,第一次必须用奇数,得不了分,后面一直用奇数,最终得分就是奇数个数减一。

点击查看代码
#include<bits/stdc++.h>

using namespace std;

int n;
int a[105];
bool is_ou;
int sum_ji;

void qwq(){
	
	cin >> n;
	is_ou = 0;sum_ji = 0;
	for(int i = 1;i <= n;++ i){
		cin >> a[i];
		if(a[i]%2 == 0) is_ou = 1;
		else sum_ji++;
	}
	
	if(is_ou){
		cout << sum_ji+1 << endl;
	}
	else{
		cout << sum_ji-1 << endl;
	}
	
}

signed main(){
	
	int t;
	cin >> t;
	while(t--) qwq();
	
	return 0;
	
} 

B

link

我们设\(x\)为上底,\(y\)为下底,\(c\)为腰。
那么\(x+c+c<y\)才能组成梯形,即\(2c<y-x\)
那么我们要让腰尽可能长,上底与下底之差尽可能小。
寻找至少有两个的最大数为腰,找差最小的两个数为上下底,判断是否满足\(x+c+c<y\)即可。

点击查看代码
#include<bits/stdc++.h>

using namespace std;

int n;
int a[200005];
int b[200005];
int m;
int x,y,c;
map<int,int> js;

void qwq(){
	
	js.clear();
	x = y = c = 0;
	
	cin >> n;
	for(int i = 1;i <= n;++ i)
		cin >> a[i],js[a[i]]++;
	
	sort(a+1,a+1+n);
	
	for(int i = n;i >= 1;-- i){
		if(js[a[i]] >= 2){
			js[a[i]] -= 2;
			c = a[i];
			break;
		}
	}
	
	if(c == 0){
		cout << -1 << endl;
		return;
	}
	
	m = 0;
	for(int i = 1;i <= n;++ i)
		if(a[i] != a[i-1]&&js[a[i]]) b[++m] = a[i];
	
	int ans = 1e8+5;
	for(int i = 1;i <= m;++ i){
		if(js[b[i]] >= 2){
			ans = 0;
			x = y = b[i];
		}
		if(i != 1&&b[i]-b[i-1] < ans){
			ans = b[i]-b[i-1];
			x = b[i-1];
			y = b[i];
		}
	}
	
	if(x+c+c > y)
		cout << x << " " << c << " " << c << " " << y << endl;
	else cout << -1 << endl;
	
}

signed main(){
	
	int t;
	cin >> t;
	while(t--) qwq();
	
	return 0;
	
}

C

link

\(DP\),设\(f_{i,0/1}\)代表考虑到第\(i\)个人,他是好人(\(1\))或骗子(\(0\))的方案数。
那么如果他是骗子,前一个人一定要是好人。
如果他是好人,分两种情况:
1.前一个人是好人(\(a_i=a_{i-1}\)时)。
2.前一个人是骗子,那么前前一个人一定是好人(\(a_i=a_{i-2}+1\)时)。
最后答案是最后一个人是骗子或好人的方案数和。

点击查看代码
#include<bits/stdc++.h>

#define mod 998244353

using namespace std;

int n;
int a[200005];
int f[200005][2];

void qwq(){
	
	cin >> n;
	for(int i = 1;i <= n;++ i) cin >> a[i];
	
	memset(f,0,sizeof(f));
	f[1][0] = 1;
	if(a[1] == 0) f[1][1] = 1;
	for(int i = 2;i <= n;++ i){
		f[i][0] = f[i-1][1];
		if(a[i] == a[i-1]) f[i][1] = f[i-1][1];
		if(a[i] == a[i-2]+1)
			f[i][1] += f[i-1][0],f[i][1] %= mod;
	}
	cout << (f[n][0]+f[n][1])%mod << endl;
	
}

signed main(){
	
	int t;
	cin >> t;
	while(t--) qwq();
	
	return 0;
	
}

D

link

差不超过\(1\)才可以相加是一个很好的性质,因为这样\(b\)数组中的一个数\(x\)要么是\(b+b\),要么是\(b+(b+1)\),那么\(b=\lfloor \frac{x}{2} \rfloor\),这样一个数\(x\)的来源就唯一确定了。
那么我们就递归拆分每一个\(b\)中的数,直到\(a\)中有拆出来的数,如果拆到\(0\)了也没找到,则凑不出。
都凑出来了并且\(a\)\(b\)的和相等即可。

点击查看代码
#include<bits/stdc++.h>

#define int long long

using namespace std;

int n,m;
int a[200005];
int b[200005];
int s;
map<int,int> am;

bool find(int x){
	if(am[x]){
		am[x]--;
		return true;
	}
	if(x == 0) return false;
	int b1 = x/2;
	int b2 = x-b1;
	if(find(b1)&&find(b2)) return true;
	else return false;
}

void qwq(){
	
	s = 0;
	am.clear();
	bool f = 1;
	
	cin >> n >> m;
	for(int i = 1;i <= n;++ i)
		cin >> a[i],am[a[i]]++,s += a[i];
	for(int i = 1;i <= m;++ i){
		cin >> b[i];s -= b[i];
		if(f&&(!find(b[i]))){
			f = 0;
		}
	}
	
	if(f&&s == 0) cout << "Yes\n";
	else cout << "No\n";
	
}

signed main(){
	
	int t;
	cin >> t;
	while(t--) qwq();
	
	return 0;
	
}
posted @ 2025-01-30 19:04  我的晴语表  阅读(35)  评论(0)    收藏  举报