训练十二
A.Valya and Letter
题意,给一个信的长宽,和信箱口的长宽,每次可以对折,问最少多少次能把信放进去。
#include<bits/stdc++.h>
using namespace std;
long long n, m, a, b;
int main() {
scanf("%lld%lld%lld%lld", &n, &m, &a, &b);
long long x = m, y = n;
long long ans1 = 0, ans2 = 0;
while (n > a || m > b) {
if (n > a) {
n = (n >> 1) + (n & 1);
ans1++;
}
if (m > b) {
m = (m >> 1) + (m & 1);
ans1++;
}
}
while (x > a || y > b) {
if (x > a) {
x = (x >> 1) + (x & 1);
ans2++;
}
if (y > b) {
y = (y >> 1) + (y & 1);
ans2++;
}
}
printf("%lld\n", min(ans1, ans2));
}
L. How Many Tests
这题开始wa了好几次,忘记了长度是给定的,所以最小也是100…00。唉,这种细节还是总是被坑
题意:一次比赛里面有若干个测试样例文件,按照01,02,03,…,15这样来排序,前面补充0,使其字典序正确。现在给出几个测试样例文件的文件名,问这次比赛最少可能有多少组样例,最多可能有多少组样例。
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
cin >> n;
char s[20];
int maxn = -1;
int len;
for(int i = 0;i < n;i++){
scanf("%s",s);
int a;
sscanf(s,"%d",&a);
//cout << a << endl;
maxn = max(maxn,a);
len = strlen(s);
}
//cout << maxn << endl;
int base = 1;
for(int i = 0;i < len;i++){
base *= 10;
}
cout << max(base/10,maxn) << endl;
cout << base - 1 << endl;
}
E. Difficult Problems
队友开始看错题目了,其实就是道水题,都不用二分
就数一数有多少个A,就可以了
题意:每次碰到一道题就写若干个A,不同数量的A代表了不同的难度,每道题的难度都不一样,问最多有几道题。
#include<bits/stdc++.h>
using namespace std;
string s;
int main(){
cin >> s;
int sum = 0;
for(int i = 0;i < s.size();i++){
if(s[i] == 'A') sum++;
}
//cin >> sum;
int res = 0;
int now = 1;
while(sum - now >= 0){
sum -= now;
now++;
res++;
}
cout << res << endl;
}
G. Flexible Segments
这个题当时应该早点发现的,自己没有拼凑出来,对数字还是没有那么有感觉。不然早该发现的,当时的直觉是是3,4,5那一块地方,但是没有去模拟一下。
结果写了个搜索出来,搜出来是3,汗颜…
题意:给定长度n,问有没有这样连续的n个正整数,将每一个数变成它旁边的数,即x变成x+1或者x-1,之后乘积不变
比如1234 == 2143
显然n为偶数的依次交换顺序即可。
#include<bits/stdc++.h>
//#define int long long
using namespace std;
/*int M;
int flag;
void init(int l,int len){
M = 1;flag = 0;
for(int i = 0;i < len;i++){
M *= (l+i);
}
}
void dfs(int l,int len,int sum){
if(flag == 1) return;
if(M % sum != 0) return;
if(len == 0){
flag = 1;
}
dfs(l+1,len-1,sum*(l-1));
dfs(l+1,len-1,sum*(l+1));
}*/
int main(){
/*int n = 3;
while(flag != 0){
int l = 1;
init(l,n);
dfs(l,n,1);
if(flag == 1){
cout << l;
}
l++;
}*/
int n;
while(~scanf("%d",&n)){
char s[] = "+-";
if(n & 1){
if(n == 1){
cout << "NO" << endl;
}
else{
cout<<"YES" <<endl;
cout <<"3" <<endl;
n -= 3;
cout << "-++";
for(int i = 0;i < n;i++){
cout << s[i&1];
}cout << endl;
}
}
else{
cout << "YES" <<endl;
cout << 1 << endl;
for(int i = 0;i < n;i++){
cout << s[i&1];
}cout << endl;
}
}
}
H. Secret Code
当时写炸了,后来换了个思路,就好写很多了。
但还是最后wa了几次,特判的时候没有写好。
题意:给你一些数字(0-9)问用这些数字能组成的最大的密文是多少,一个数字是密文的条件是,每三个连续的数字组成的三位数是三的倍数。
思路:将数分为三种(mod 3),在这三个筒里面把数字从大到小排好,因为只要确定前三个数的种类,后面肯定是依次循环,直接一个一个拿出来就好了。
炸的代码
#include<bits/stdc++.h>
using namespace std;
struct Node{
int id;
int sum;
bool operator < (const Node&x)const{
return sum > x.sum;
}
}L[3];
vector<int>R[5];
int main(){
for(int i = 0;i < 10;i++){
int t;
cin >> t;
for(int i = 0;i < t;i++){
R[i%3].push_back(i);
}
}
for(int i = 0;i < 3;i++){
L[i].id = i;
L[i].sum = L[i].size();
sort(R[i].begin(),R[i].end());
}
sort(L,L+3,greater<int>());
string r1,r2,r3;
//case 1: 横着取 0,1,2
int len1 = L[2].sum;
if(L[1].sum > L[2].sum) len1++;
if(L[0].sum > L[2].sum) len1++;
vector<int>t1;
for(int i = 0;i < len1;i++){
t1.push_back(R[0][i]);
t1.push_back(R[1][i]);
t1.push_back(R[2][i]);
}
if(R[L[1].id].size() > R[L[2].id].size()){
t1.push_back(R[L[0].id][len1]);
t1.push_back(R[L[1].id][len1]);
}
else{
if(R[L[0].id].size() > R[L[2].id].size()){
t1.push_back(R[L[0].id][len1]);
}
}
sort(t1.begin(),t1.end(),greater<int>());
for(int i = 0;i < t1.size();i++){
r1 += (char)(t1[i] - '0')
}
//case 2:竖着 1, 1, 1
int len2 = L[0].sum;
for(int i = 0;i < len2;i++){
r2 += (char)(R[L[0].id][i] - '0');
}
//case 3:竖着 1, 1, 2
//不 写 了,他妈的,太难写了
//换个思路写
}
过的代码
#include<bits/stdc++.h>
using namespace std;
vector<int>L[3];
string solve(string tp) {
if ((tp[0] - '0' + tp[1] - '0' + tp[2] - '0') % 3 != 0) return "";
//cout << tp << endl;
int i[] = { 0,0,0 };
int ind = 0;
string res = "";
while (1) {
int now = (tp[ind] - '0');
if (i[now] == L[now].size()) break;
res += (char)(L[now][i[now]] + '0');
i[now]++;
ind++;
ind %= 3;
}
return res;
}
int main() {
for (int i = 0; i < 10; i++) {
int t;
cin >> t;
for (int j = 0; j < t; j++) {
L[i % 3].push_back(i);
}
}
for (int i = 0; i < 3; i++) {
sort(L[i].begin(), L[i].end(), greater<int>());
}
vector<string>S;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
for (int k = 0; k < 3; k++) {
string tmp = "";
tmp += (char)(i + '0'); tmp += (char)(j + '0'); tmp += (char)(k + '0');
//cout << tmp;
S.push_back(tmp);
}
}
}
string maxn = "";
for (int i = 0; i < S.size(); i++) {
string s = solve(S[i]);
//cout << S[i] << endl;
//cout << s << endl;
if (s.size() > maxn.size()) {
maxn = s;
}
if (s.size() == maxn.size()) {
if (s > maxn) {
maxn = s;
}
}
}
string res = "";
int flag = 0;
for (int i = 0; i < maxn.size(); i++) {
if (flag == 1) {
res += maxn[i];
}
if (!flag && maxn[i] != '0') {
res += maxn[i]; flag = 1;
}
}
if (res == "") {
cout << "0" << endl;
}
else {
cout << res << endl;
}
}
D. Berland Railroads
给定n和点的度数序列,求一个树,使其任意两点距离的最大值最小。
队友讨论后决定用贪心做。
#include<bits/stdc++.h>
using namespace std;
int n;
struct Node{
int id;
int deg;
bool operator < (const Node& x)const{
return deg < x.deg;
}
}L[200050];
int main(){
cin >> n;
for(int i = 0;i < n;i++){
cin >> L[i].deg;
L[i].id = i+1;
}
sort(L,L+n);
queue<Node>Q;
Q.push(L[0]);
int ind = 1;
while(!Q.empty()){
Node tp = Q.front();Q.pop();
for(int i = 0;i < tp.deg;i++){
L[ind].deg--;
Q.push(L[ind]);
ind++;
cout << tp.id << " " << L[ind].id << endl;
}
}
}
自己没有解决的问题。