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;
}

浙公网安备 33010602011771号