CodeForces - 437
A. The Child and Homework
题目描述:
Once upon a time a child got a test consisting of multiple-choice questions as homework. A multiple-choice question consists of four choices: A, B, C and D. Each choice has a description, and the child should find out the only one that is correct.
Fortunately the child knows how to solve such complicated test. The child will follow the algorithm:
- If there is some choice whose description at least twice shorter than all other descriptions, or at least twice longer than all other descriptions, then the child thinks the choice is great.
- If there is exactly one great choice then the child chooses it. Otherwise the child chooses C (the child think it is the luckiest choice).
You are given a multiple-choice questions, can you predict child's choose?
Input
The first line starts with "A." (without quotes), then followed the description of choice A. The next three lines contains the descriptions of the other choices in the same format. They are given in order: B, C, D. Please note, that the description goes after prefix "X.", so the prefix mustn't be counted in description's length.
Each description is non-empty and consists of at most 100 characters. Each character can be either uppercase English letter or lowercase English letter, or "_".
Output
Print a single line with the child's choice: "A", "B", "C" or "D" (without quotes).
题意:
简单来说就是懵选择题答案,三长一短选短,三短一长选长,(至少短一半或长一倍)
思路:
直接模拟一下
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <stdlib.h>
#include <sstream>
#include <map>
#include <set>
using namespace std;
#define inf 0x3f3f3f3f
#define MAX 200000 + 50
#define endl '\n'
#define seed 13331
#define mod 1000000000 + 7
#define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define mem(a,b) memset((a),(b),sizeof(a))
typedef long long ll ;
//不开longlong见祖宗!
//inline __int128 read(){__int128 x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-'){f = -1;}ch = getchar();}while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}return x * f;}
//inline void print(__int128 x){if(x < 0){putchar('-');x = -x;}if(x > 9){print(x / 10);}putchar(x % 10 + '0');}
inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
inline void write(int x){if (x < 0) {x = ~x + 1; putchar('-');}if (x > 9){write(x / 10);}putchar(x % 10 + '0');}
ll num[10];
int main(){
string s;
for(int i = 1; i <= 4; ++i){
cin>>s;
num[i] = s.size() - 2;//记录长度
}
int ans = 0, k = 0;//k用来统计有几个是长两倍或短两倍的,ans用来记录选项的位置
for(int i = 1; i <= 4; ++i){
int a = 0, b = 0;
for(int j = 1; j <= 4; ++j){
if(i == j)continue;//相同就跳过
if(num[i] >= 2 * num[j])++a;
if(num[i] * 2 <= num[j])++b;
}
if(a == 3 || b == 3){
++k;
ans = i;
}
}
if(k == 1)cout<<(char)('A' + ans - 1)<<endl;
else cout<<"C\n";
return 0;
}
B. The Child and Set
题目描述:
At the children's day, the child came to Picks's house, and messed his house up. Picks was angry at him. A lot of important things were lost, in particular the favorite set of Picks.
Fortunately, Picks remembers something about his set S:
- its elements were distinct integers from 1 to limit;
- the value of was equal to sum; here lowbit(x) equals 2k where k is the position of the first one in the binary representation of x. For example, lowbit(100102) = 102, lowbit(100012) = 12, lowbit(100002) = 100002 (binary representation).
Can you help Picks and find any set S, that satisfies all the above conditions?
Input
The first line contains two integers: sum, limit (1 ≤ sum, limit ≤ 105).
Output
In the first line print an integer n (1 ≤ n ≤ 105), denoting the size of S. Then print the elements of set S in any order. If there are multiple answers, print any of them.
If it's impossible to find a suitable set, print -1.
题意:
lowbit(x)和树状数组中的一样,设二进制从后往前第一个1的位置是y,则lowbit(x) = $$2^{y - 1}$$,问你能不能用1到limit内的任意数量的树凑出来sum的值?
思路:
其实是个贪心!
首先,lowbit = x & (-x),我们可以对limit打个循环,算出所有的数的lowbit,他们的值都是2的k次方,k是整数。
现在问题就相当于能不能用一堆$$2^{k}$$的数去凑出sum,转换一下,就相当于凑钱问题:给你面值为……的纸币若干,问你能不能刚好凑出sum块钱,只需要对其排个序,从大到小循环即可
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <stdlib.h>
#include <sstream>
#include <map>
#include <set>
using namespace std;
#define inf 0x3f3f3f3f
#define MAX 100000 + 50
#define endl '\n'
#define seed 13331
#define mod 1000000000 + 7
#define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define mem(a,b) memset((a),(b),sizeof(a))
typedef long long ll ;
//不开longlong见祖宗!
//inline __int128 read(){__int128 x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-'){f = -1;}ch = getchar();}while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}return x * f;}
//inline void print(__int128 x){if(x < 0){putchar('-');x = -x;}if(x > 9){print(x / 10);}putchar(x % 10 + '0');}
inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
inline void write(int x){if (x < 0) {x = ~x + 1; putchar('-');}if (x > 9){write(x / 10);}putchar(x % 10 + '0');}
int n, m, len;
int tr[MAX];
int ans[MAX];
bool p ;
int f(int x){
return x & -x;
}
int main(){
n = IntRead();
m = IntRead();
for(int i = 1; i <= m; ++i)tr[i] = f(i);
for(int i = m; i >= 1; --i){
if(n >= tr[i]){
n -= tr[i];
ans[++len] = i;
}
if(n == 0)break;
}
if(n == 0){
cout<<len<<endl;
for(int i = 1; i <= len; ++i)i == 1 ? cout<<ans[i] : cout<<' '<<ans[i];
cout<<endl;
}
else cout<<-1<<endl;
return 0;
}
C - The Child and Toy
题目描述:
On Children's Day, the child got a toy from Delayyy as a present. However, the child is so naughty that he can't wait to destroy the toy.
The toy consists of n parts and m ropes. Each rope links two parts, but every pair of parts is linked by at most one rope. To split the toy, the child must remove all its parts. The child can remove a single part at a time, and each remove consume an energy. Let's define an energy value of part i as v**i. The child spend v**f1 + v**f2 + ... + vfk energy for removing part i where f1, f2, ..., f**k are the parts that are directly connected to the i-th and haven't been removed.
Help the child to find out, what is the minimum total energy he should spend to remove all n parts.
题意:
n个点m条边的图,要将这个图拆开成n个点,拆点x时的成本是与他相连的所有的点的权值,问拆完后最小成本是多少
思路:
拆点=拆边,对于每条边,我们只需要花费min(x, y)的成本即可拆掉
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <stdlib.h>
#include <sstream>
#include <map>
#include <set>
using namespace std;
#define inf 0x3f3f3f3f
#define MAX 100000 + 50
#define endl '\n'
#define seed 13331
#define mod 1000000000 + 7
#define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define mem(a,b) memset((a),(b),sizeof(a))
typedef long long ll ;
//不开longlong见祖宗!
//inline __int128 read(){__int128 x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-'){f = -1;}ch = getchar();}while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}return x * f;}
//inline void print(__int128 x){if(x < 0){putchar('-');x = -x;}if(x > 9){print(x / 10);}putchar(x % 10 + '0');}
inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
inline void write(int x){if (x < 0) {x = ~x + 1; putchar('-');}if (x > 9){write(x / 10);}putchar(x % 10 + '0');}
int n, m, x, y;
int tr[MAX];
int main(){
cin>>n>>m;
int sum = 0;
for(int i = 1; i <= n; ++i)tr[i] = IntRead();
for(int i = 1; i <= m; ++i){
x = IntRead();y = IntRead();
sum += min(tr[x], tr[y]);
}
cout<<sum<<endl;
return 0;
}
D - Devu and Partitioning of the Array-CodeForces - 439C
题目描述:
Devu being a small kid, likes to play a lot, but he only likes to play with arrays. While playing he came up with an interesting question which he could not solve, can you please solve it for him?
Given an array consisting of distinct integers. Is it possible to partition the whole array into k disjoint non-empty parts such that p of the parts have even sum (each of them must have even sum) and remaining k - p have odd sum? (note that parts need not to be continuous).
If it is possible to partition the array, also give any possible way of valid partitioning
题意:
给你n个数,让你分成k组,设每组的所有数的和为x,要求x为偶数的要有p组,x为奇数的要有k-p组,问你能不能分成功
思路:
设num1为奇数的数量,num2为偶数的数量
奇数可以凑成偶数,但偶数不可以凑成奇数,所以对于x为奇数的组,只能有奇数个奇数来凑,所以如果num1小于k-p,则输出NO,同时,如果num1-k+p是奇数,也就是剩下的奇数的个数如果是奇数,就没法凑出完全偶数来,输出NO,再就是如果num2 + (num1 - k + p) / 2 < p,也就是偶数的数量再加上剩下的奇数的数量的一半比p小,则输出NO,其他的情况就都可以凑出来
凑的时候,先搞k - p行单个的奇数的,再搞p - 1行单个的偶数的,剩下的全放最后一排即可
这里面有很多细节要注意🥷🏿
大的方向是讨论一下偶数的数量是否dayu等于p,如果是,就再讨论一下p = 0,以及p!=0,如果不是,就直接做
代码太臭了,调了一晚上都,不想再解释了, 就这样叭
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <stdlib.h>
#include <sstream>
#include <map>
#include <set>
using namespace std;
#define inf 0x3f3f3f3f
#define MAX 100000 + 50
#define endl '\n'
#define seed 13331
#define mod 1000000000 + 7
#define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define mem(a,b) memset((a),(b),sizeof(a))
typedef long long ll ;
//不开longlong见祖宗!
//inline __int128 read(){__int128 x = 0, f = 1;char ch = getchar();while(ch < '0' || ch > '9'){if(ch == '-'){f = -1;}ch = getchar();}while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}return x * f;}
//inline void print(__int128 x){if(x < 0){putchar('-');x = -x;}if(x > 9){print(x / 10);}putchar(x % 10 + '0');}
inline int IntRead(){char ch = getchar();int s = 0, w = 1;while(ch < '0' || ch > '9'){if(ch == '-') w = -1;ch = getchar();}while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0';ch = getchar();}return s * w;}
inline void write(int x){if (x < 0) {x = ~x + 1; putchar('-');}if (x > 9){write(x / 10);}putchar(x % 10 + '0');}
int n, k, p, t;
int odd[MAX];//奇数
int even[MAX];//偶数
int num1, num2;
int main(){
cin>>n>>k>>p;
for(int i = 1; i <= n; ++i){
t = IntRead();
if(t % 2 == 0)even[++num2] = t;
else odd[++num1] = t;
}
if(num1 < k - p || (num1 - k + p) % 2 == 1 || num2 + (num1 - k + p) / 2 < p)cout<<"NO\n";
else{
cout<<"YES\n";
if(num2 >= p){
if(p == 0){
for(int i = 1; i <= k - p - 1; ++i)cout<<1<<' '<<odd[i]<<endl;
int x = num1 + num2 - k + 1;
cout<<x;
for(int i = k - p; i <= num1; ++i)cout<<' '<<odd[i];
for(int i = 1; i <= num2; ++i)cout<<' '<<even[i];
cout<<endl;
}
if(p != 0){
for(int i = 1; i <= k - p; ++i)cout<<1<<' '<<odd[i]<<endl;
for(int i = 1; i <= p - 1; ++i)cout<<1<<' '<<even[i]<<endl;
int x = num1 + num2 - k + 1;
cout<<x;
for(int i = k - p + 1; i <= num1; ++i)cout<<' '<<odd[i];
for(int i = p; i <= num2; ++i)cout<<' '<<even[i];
cout<<endl;
}
}
else {
for(int i = 1; i <= k - p; ++i)cout<<1<<' '<<odd[i]<<endl;
for(int i = 1; i <= num2; ++i)cout<<1<<' '<<even[i]<<endl;
int x = p - num2;
int l = k - p + 1;
// int num = num1 - p + k - 2 * x;
for(int i = 1; i <= x - 1; ++i){
cout<<2<<' '<<odd[l]<<' '<<odd[l + 1]<<endl;
l += 2;
}
if(num1 - k + p - 2 * (x - 1) != 0){
cout<<num1 - k + p - 2 * (x - 1);
for(int i = l; i <= num1; ++i)cout<<' '<<odd[i];
}
cout<<endl;
}
}
return 0;
}