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 998244353using 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 longusing 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;}