热身赛 <C>
题意:
给一个数赋初值1,只能对这个数进行*2, +1, -1, 这三种操作,问他能达到所给数的最小步数。
思路:
DP没得说,但我DP不熟,赛后回味了一下,一直以为是贪心,其实就看当前状态是怎么由上一个状态转移过来的就好了,要预处理一下,代码注释很详细。
本人AC代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 2e6 + 5;
int dp[maxn]; //步数
int n;
int main() {
dp[1] = 0; //1转移到1步数为0
for(int i = 2; i <= maxn; i++) { //预处理
if(i & 1) { //奇数时
int t1 = dp[(i - 1) / 2] + 2; //由它前一个数乘2加1转移过来, 所需2步
int t2 = dp[(i + 1) / 2] + 2; //由它前一个数乘2减1转移过来, 所需2步
int tmp = min(t1, t2);
dp[i] = min(dp[i - 1] + 1, tmp); //由它前一个数加1转移过来, 所需1步, 然后取上述三者最小值
}
else { //偶数时
int t1 = dp[(i - 2) / 2] + 3; //由它前一个数乘2加1再加1转移过来, 所需3步
int t2 = dp[(i + 2) / 2] + 3; //由它前一个数乘2减1再减1转移过来, 所需3步
int tmp = min(t1, t2);
dp[i] = min(dp[i / 2] + 1, tmp); //由它前一个数乘2转移过来, 所需1步, 然后取上述三者最小值
}
}
while(cin >> n && n) {
cout << dp[n] << endl;
}
}
正赛:
<H>
题意:给两个数 x, y,求 x + y + Gcd(x, y)
思路:签到题,水的要命。
本人AC代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
int gcd(int x, int y) {
if(x % y == 0) return y;
else return gcd(y, x % y);
}
int main() {
int cas;
cin >> cas;
while(cas--) {
int n, m;
cin >> n >> m;
cout << n + m + gcd(n, m) << endl;
}
}
<B>
题意:
给四个串,输入一个串,看输入的串是给定四个串里哪几个串的不连续子串,区分大小写。
思路:签到题,直接暴力就好了,按照所给用string初始化四个串,然后把输入串的字符按顺序枚举即可。写的有点笨重,没爱多想,就是个水题,觉得没必要太优化写法。当时赛场上那个配置的Vim的strlen( )函数不变色,回来补的时候没问题了,还是自己的Vim用着舒服。
本人AC代码:
#include <cstdio>
#include <cstdlib>
#include <string>
#include <cstring>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <iostream>
#include <algorithm>
using namespace std;
queue <int> qua;
map <int, int> mp;
int cas;
char s[55];
string s1 = "KanbaraAkihito";
string s2 = "KuriyamaMirai";
string s3 = "NaseHiroomi";
string s4 = "NaseMitsuki";
string ss1 = "Kanbara Akihito";
string ss2 = "Kuriyama Mirai";
string ss3 = "Nase Hiroomi";
string ss4 = "Nase Mitsuki";
int main() {
cin >> cas;
while(cas--) {
int cnt = 0;
scanf("%s", s);
int l = strlen(s);
int c = 0;
bool f1 = 1, f2 = 1, f3 = 1, f4 = 1;
int pos = 0;
for(int i = 0; i < l; i++) {
for(int j = pos; j < 15; j++) {
if(s1[j] == s[i]) {
c++;
pos = j + 1;
break;
}
}
}
if(c >= l) cnt++;
else f1 = 0;
c = 0;
pos = 0;
for(int i = 0; i < l; i++) {
for(int j = pos; j < 14; j++) {
if(s2[j] == s[i]) {
c++;
pos = j + 1;
break;
}
}
}
if(c >= l) cnt++;
else f2 = 0;
c = 0;
pos = 0;
for(int i = 0; i < l; i++) {
for(int j = pos; j < 12; j++) {
if(s3[j] == s[i]) {
c++;
pos = j + 1;
break;
}
}
}
if(c >= l) cnt++;
else f3 = 0;
c = 0;
pos = 0;
for(int i = 0; i < l; i++) {
for(int j = pos; j < 12; j++) {
if(s4[j] == s[i]) {
c++;
pos = j + 1;
break;
}
}
}
if(c >= l) cnt++;
else f4 = 0;
cout << cnt << endl;
if(f1) cout << ss1 << endl;
if(f2) cout << ss2 << endl;
if(f3) cout << ss3 << endl;
if(f4) cout << ss4 << endl;
}
}
<E>
题意:
日期的表示方法有两种,月/日/年 and 年/月/日,按照格式输入a / b / c,看符合两种表示方式的哪种,如果都符合,就输出这不同两天之间相差多少天;如果只有一种合法或者两种表示方法是同一天,比如 01/02/03 和 02/02/02 ,则按月日年形式输出唯一合法的日期,至少有一种表示方式合法。
思路:
最恶心的签到,给我恶心完了简直,回来补题换了种很系统的写法,先写一个chk函数判断日期合法与否,如下:
bool chk(int y, int m, int d) {
bool flg = 1;
if(m > 12 || m == 0) flg = 0;
if(m == 1 || m == 3 || m == 5 || m == 7 || m == 8 || m == 10 || m == 12) {
if(d == 0 || d > 31) flg = 0;
}
else if(m == 4 || m == 6 || m == 9 || m == 11) {
if(d == 0 || d > 30) flg = 0;
}
else if(m == 2) {
if( (y % 4 == 0 && y % 100 != 0) || (y % 400 == 0) ) {
if(d == 0 || d > 29) flg = 0;
}
else {
if(d == 0 || d > 28) flg = 0;
}
}
return flg;
}
再将输入的两种表示形式都写出来,看有几个合法,如果两个合法,那就分别算他俩与2000/1/1之间的天数,再求差取绝对值即可,如果只有一种满足,那就按题意输出即可,没什么难度,但是非常考验C语言功底,虽然我不是大佬可能没资格说这种话,但是,还是建议初学者认真做一下这题,如果这种恶心题一直扔着不做,以后碰到恶心题就永远做不出来,毕竟身为ACM,AC即一切,如果这题WA到比赛结束,说什么都白扯,话不多说,放下我代码。
本人AC代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
map <int, int> mp;
queue <int> qua;
stack <char> stk;
vector <int> vec;
set <int> st;
int cas;
char s[12];
int a, b, c;
string M[13];
bool chk(int y, int m, int d) {
bool flg = 1;
if(m > 12 || m == 0) flg = 0;
if(m == 1 || m == 3 || m == 5 || m == 7 || m == 8 || m == 10 || m == 12) {
if(d == 0 || d > 31) flg = 0;
}
else if(m == 4 || m == 6 || m == 9 || m == 11) {
if(d == 0 || d > 30) flg = 0;
}
else if(m == 2) {
if( (y % 4 == 0 && y % 100 != 0) || (y % 400 == 0) ) {
if(d == 0 || d > 29) flg = 0;
}
else {
if(d == 0 || d > 28) flg = 0;
}
}
return flg;
}
int main() {
cin >> cas;
while(cas--) {
int D[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
M[1] = "January", M[2] = "February", M[3] = "March", M[4] = "April", M[5] = "May", M[6] = "June";
M[7] = "July", M[8] = "August", M[9] = "September", M[10] = "October", M[11] = "November", M[12] = "December";
memset(s, 0, sizeof(s)); //这句必须加,虽然不知道为啥需要清空,但是不清空就会WA
scanf("%s", s);
a = s[1] - '0' + 10 * (s[0] - '0');
b = s[4] - '0' + 10 * (s[3] - '0');
c = s[7] - '0' + 10 * (s[6] - '0');
int ya = 2000 + a, ma = b, da = c;
int yb = 2000 + c, mb = a, db = b;
/* 测一下输出
cout << ya << "/" << ma << "/" << da << endl; //年月日
if(chk(ya, ma, da)) cout << "Yes" << endl;
else cout << "No" << endl;
cout << yb << "/" << mb << "/" << db << endl; //月日年
if(chk(yb, mb, db)) cout << "Yes" << endl;
else cout << "No" << endl;
*/
if(chk(ya, ma, da) + chk(yb, mb, db) == 2) {
if(ya == yb && ma == mb && da == db) { //两种都合法看是不是同一天
cout << M[ma];
printf(" %d, %d\n", da, ya);
}
else {
int ans = 0, res = 0;
for(int i = 2000; i <= ya - 1; i++) {
if( (i % 4 == 0 && i % 100 != 0) || (i % 400 == 0) ) ans += 366;
else ans += 365;
}
if( (ya % 4 == 0 && ya % 100 != 0) || (ya % 400 == 0) ) D[2]++;
for(int i = 1; i <= ma - 1; i++) ans += D[i];
ans += da;
D[2] = 28;
for(int i = 2000; i <= yb - 1; i++) {
if( (i % 4 == 0 && i % 100 != 0) || (i % 400 == 0) ) res += 366;
else res += 365;
}
if( (yb % 4 == 0 && yb % 100 != 0) || (yb % 400 == 0) ) D[2]++;
for(int i = 1; i <= mb - 1; i++) res += D[i];
res += db;
cout << abs(ans - res) << endl;
}
}
else {
if(chk(ya, ma, da)) {
cout << M[ma];
printf(" %d, %d\n", da, ya);
}
else if(chk(yb, mb, db)) {
cout << M[mb];
printf(" %d, %d\n", db, yb);
}
}
}
}