热身赛
题意:
给一个数赋初值1,只能对这个数进行*2, +1, -1, 这三种操作,问他能达到所给数的最小步数。
思路:
DP没得说,但我DP不熟,赛后回味了一下,一直以为是贪心,其实就看当前状态是怎么由上一个状态转移过来的就好了,要预处理一下,代码注释很详细。
本人AC代码:
#include
#include
#include
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;
}
}
正赛:
题意:给两个数 x, y,求 x + y + Gcd(x, y)
思路:签到题,水的要命。
本人AC代码:
#include
#include
#include
#include
#include
#include
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;
}
}
题意:
给四个串,输入一个串,看输入的串是给定四个串里哪几个串的不连续子串,区分大小写。
思路:签到题,直接暴力就好了,按照所给用string初始化四个串,然后把输入串的字符按顺序枚举即可。写的有点笨重,没爱多想,就是个水题,觉得没必要太优化写法。当时赛场上那个配置的Vim的strlen( )函数不变色,回来补的时候没问题了,还是自己的Vim用着舒服。
本人AC代码:
#include
#include
#include
#include
#include
#include
}
题意:
日期的表示方法有两种,月/日/年 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
#include
#include
#include
#include
#include
#include
#include
#include