第一次类似组队那样练题,做到后期感觉自己还是后劲不足,难题还是做不来。
下午做出了6道题目,ALGHJB,可能水题比较多,合胃口,但是加深难度之后,还是力不从心,想拿铜还是要苦练。
等题加入题库了再加链接。
A题:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3869
大水题,sb的是我开场wa了一发 。,。
因为数据实在小,所以搞了一个大暴力,然后<=的=号手滑加了上去。。。
深表遗憾。。。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <cmath> #include <stack> #include <vector> #include <queue> #include <map> #include <climits> #include <cassert> #define LL long long using namespace std; const int maxn = 1000 + 10; const int inf = 0x3f3f3f3f; const double eps = 1e-8; const double pi = 4 * atan(1.0); const double ee = exp(1.0); int n; int a[maxn]; int main() { #ifdef LOCAL freopen("in.txt", "r", stdin); #endif // LOCAL int ncase; scanf("%d", &ncase); while (ncase--) { memset(a, 0, sizeof(a)); scanf("%d", &n); for (int i = 0; i < n; i++) { int x; scanf("%d", &x); a[x]++; } int posans = -1; int maxval = 0; bool flag = true; for (int i = 1; i < maxn; i++) { if (maxval < a[i]) { maxval = a[i]; posans = i; } } for (int i = 1; i < maxn; i++) { if (maxval == a[i] && posans != i) { flag = false; break; } } if (flag) { printf("%d\n", posans); } else { printf("Nobody\n"); } } return 0; }
L:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3880
学弟A的,听说是个大水题。
。,。
代码:
#include <cstdio> int main() { int n,i,j,k,t,x; scanf("%d",&t); while(t--) { scanf("%d",&n); k=0; for(i=1;i<=n;i++) { scanf("%d",&x); if(x>6000)k++; } printf("%d\n",k); } return 0; }果然
G:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3875
题目看懂就好做了,大模拟。
排个序,找到三种菜的价格中位数,累和输出。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <cmath> #include <stack> #include <vector> #include <queue> #include <map> #include <climits> #include <cassert> #define LL long long using namespace std; const int maxn = 100 + 10; const int inf = 0x3f3f3f3f; const double eps = 1e-8; const double pi = 4 * atan(1.0); const double ee = exp(1.0); struct C { string name; int price; } ss[maxn], mm[maxn], dd[maxn]; bool cmp(C a, C b) { if (a.price == b.price) return a.name < b.name; return a.price < b.price; } int main() { #ifdef LOCAL freopen("in.txt", "r", stdin); #endif // LOCAL int ncase; scanf("%d", &ncase); while (ncase--) { int s, m, d; scanf("%d%d%d", &s, &m, &d); for (int i = 0; i < s; i++) { cin >> ss[i].name >> ss[i].price; } for (int i = 0; i < m; i++) { cin >> mm[i].name >> mm[i].price; } for (int i = 0; i < d; i++) { cin >> dd[i].name >> dd[i].price; } sort(ss, ss + s, cmp); sort(mm, mm + m, cmp); sort(dd, dd + d, cmp); int poss = s / 2; int posm = m / 2; int posd = d / 2; printf("%d ", ss[poss].price + mm[posm].price + dd[posd].price); cout << ss[poss].name << " " << mm[posm].name << " " << dd[posd].name << endl; } return 0; }
H:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3876
重要的点就是找到某年的5月1号是星期几。
用了一个算某天是星期几的算法。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <cmath> #include <stack> #include <vector> #include <queue> #include <map> #include <climits> #include <cassert> #define LL long long using namespace std; const int maxn = 100 + 10; const int inf = 0x3f3f3f3f; const double eps = 1e-8; const double pi = 4 * atan(1.0); const double ee = exp(1.0); int whatday(int d, int m, int y) { int ans; if (m == 1 || m == 2) { m += 12; y--; } if ((y < 1752) || (y == 1752 && m < 9) || (y == 1752 && m == 9 && d < 3)) ans = (d + 2 * m + 3 * (m + 1) / 5 + y + y / 4 + 5) % 7; else ans = (d + 2 * m + 3 * (m + 1) / 5 + y + y / 4 - y / 100 + y / 400) % 7; return ans + 1; } int main() { #ifdef LOCAL freopen("in.txt", "r", stdin); #endif // LOCAL int ncase; scanf("%d", &ncase); while (ncase--) { int year; scanf("%d", &year); int t = whatday(1, 5, year); int ans; if (t == 1) ans = 9; if (t == 2) ans = 6; if (t == 3) ans = 5; if (t == 4) ans = 5; if (t == 5) ans = 5; if (t == 6) ans = 5; if (t == 7) ans = 6; cout << ans << endl; } return 0; }
J:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3878
- - 这题,我用了一个笨方法,把转换图搞出来,然后map一一对应。
还有一个点,就是判断map键值是否存在那个函数的用法。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <cmath> #include <stack> #include <vector> #include <queue> #include <map> #include <climits> #include <cassert> #define LL long long using namespace std; const int maxn = 1000000 + 10; const int inf = 0x3f3f3f3f; const double eps = 1e-8; const double pi = 4 * atan(1.0); const double ee = exp(1.0); map<char, char> key; void init() { key['-'] = '['; key['_'] = '{'; key['='] = ']'; key['+'] = '}'; key['Q'] = '"'; key['q'] = '\''; key['W'] = '<'; key['w'] = ','; key['E'] = '>'; key['e'] = '.'; key['R'] = 'P'; key['r'] = 'p'; key['T'] = 'Y'; key['t'] = 'y'; key['Y'] = 'F'; key['y'] = 'f'; key['U'] = 'G'; key['u'] = 'g'; key['I'] = 'C'; key['i'] = 'c'; key['O'] = 'R'; key['o'] = 'r'; key['P'] = 'L'; key['p'] = 'l'; key['{'] = '?'; key['['] = '/'; key['}'] = '+'; key[']'] = '='; key['S'] = 'O'; key['s'] = 'o'; key['D'] = 'E'; key['d'] = 'e'; key['F'] = 'U'; key['f'] = 'u'; key['G'] = 'I'; key['g'] = 'i'; key['H'] = 'D'; key['h'] = 'd'; key['J'] = 'H'; key['j'] = 'h'; key['K'] = 'T'; key['k'] = 't'; key['L'] = 'N'; key['l'] = 'n'; key[':'] = 'S'; key[';'] = 's'; key['"'] = '_'; key['\''] = '-'; key['Z'] = ':'; key['X'] = 'Q'; key['C'] = 'J'; key['V'] = 'K'; key['B'] = 'X'; key['N'] = 'B'; key['<'] = 'W'; key['>'] = 'V'; key['?'] = 'Z'; key['z'] = ';'; key['x'] = 'q'; key['c'] = 'j'; key['v'] = 'k'; key['b'] = 'x'; key['n'] = 'b'; key[','] = 'w'; key['.'] = 'v'; key['/'] = 'z'; } bool isExist(const char& keyName) { return ( key.find(keyName) != key.end() ); } char str[maxn]; char ans[maxn]; int main() { #ifdef LOCAL freopen("in.txt", "r", stdin); #endif // LOCAL init(); while (gets(str)) { int len = strlen(str); for (int i = 0; i < len; i++) { if (isExist(str[i])) { ans[i] = key[str[i]]; } else { ans[i] = str[i]; } } ans[len] = '\0'; printf("%s\n", ans); } return 0; }
B:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3870
实验室退役队员亮GG在学java之余顺手过来A的题。
还没有详细看。
大致思路是将这些点按照二进制的第一个1出现在第几个位置来分类,然后搞一下就好啦。
更新:
记录每个数的二进制最高位在第几位,然后每个数扫一遍,扫他的二进制数。
若这个数的某一位为0,并且和他异或的小于他的数的二进制最高为1,则异或将大于这俩数,开个bit直接计数就行了。
需要注意的是,pos是可以到达0的,另外,pos是不能开到 1 << 32 的,因为爆了。。。。。。。。。。。。。。。
还有就是,LL。
代码(亮GG版):
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; const int maxN = 1e5 + 10; int n, arr[maxN], ans[35][35], num[35]; int main() { int ncase; cin>>ncase; while(ncase--) { long long result = 0; cin>>n; memset( ans, 0, sizeof(ans)); memset( num, 0, sizeof(num)); for(int i = 1; i <= n; ++i) scanf("%d", arr + i); sort( arr + 1, arr + n + 1); int edge = 2, t = 1; for(int i = 1; i <= n; ) { while(arr[i] < edge && i <= n) { for(int j = t-1; j >= 1; j--) { if((arr[i] & (1<<(j-1))) == 0) ans[t][j]++; } num[t]++; i++; } t++; edge *= 2; } for(int i = 32; i >= 1; i--) for(int j = i - 1; j >= 1; j--) { long long t = ans[i][j]; t *= num[j]; result = result + t; } cout<<result<<endl; } return 0; }
代码(update版):
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <cmath> #include <stack> #include <vector> #include <queue> #include <map> #define LL long long #define lson lo, mi, rt << 1 #define rson mi + 1, hi, rt << 1 | 1 using namespace std; const int maxn = 100000 + 10; const int inf = 0x3f3f3f3f; const double eps = 1e-8; const double pi = acos(-1.0); const double ee = exp(1.0); int bit[35]; int a[maxn]; int main() { #ifdef LOCAL freopen("in.txt", "r", stdin); #endif // LOCAL int ncase; scanf("%d", &ncase); while (ncase--) { memset(bit, 0, sizeof(bit)); int n; scanf("%d", &n); for (int i = 0; i < n; i++) { scanf("%d", &a[i]); for (int j = 31; j >= 0; j--) { if (a[i] & (1 << j)) { bit[j]++; // cout << a[i] << " " << j << endl; break; } } } LL ans = 0; for (int i = 0; i < n; i++) { int pos = 31;/// while (pos >= 0) { if (a[i] & (1 << pos)) break; pos--; } while (pos >= 0)/// { if ((a[i] & (1 << pos)) == 0) { ans += (LL)bit[pos]; } pos--; } } printf("%lld\n", ans); } return 0; }
然后接下来我就开始搞D题,各种乱七八糟的想法。
于是就没做出来。
待更新D题。
D:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3872
真是遗憾的一题。
这道题目不会做折射出两点:首先,dp等于没练;其次,数学思维还是不行。
看完别人的题解瞬间就懂了的那种。
题意:
给n个数,找出他连续的子集,计算子集内独一无二的元素之和,最后求出所有前述特点子集的和。
解析:
看下面例子:
现在有元素,计算过程如下(括号中代表此元素出现次数)
例子1:
2 3 4 5 6 6 5
2(1) 3(1) 4(1) 5(1) 6(1) 6(1) 5(1)
2 + 3(2) 3 + 4(2) 4 + 5(2) 5 + 6(2) 6(2) 6 + 5(2)
2 + 3 + 4(3) 3 + 4 + 5(3) 4 + 5 + 6(3) 5 + 6(3) 6 + 5(3)
2 + 3 + 4 + 5(4) 3 + 4 + 5 + 6(4) 4 + 5 + 6(4) 6 + 5(4)
2 + 3 + 4 + 5 + 6(5) 3 + 4 + 5 + 6(4) 4 + 6 + 5(5)
2 + 3 + 4 + 5 + 6(5) 3 + 4 + 6 + 5(6)
2 + 3 + 6 + 5(7)
例子2:
2 3 4 3 2 3
2(1) 3(1) 4(1) 3(1) 2(1) 3(1)
2+3(2) 3+4(2) 4+3(2) 3+2(2) 2+3(2)
2+3+4(3) 3+4(3) 4+3+2(3) 3+2(3)
2+3+4(4) 3+4+2(4) 4+3+2(4)
2+3+4(5) 3+4+2(5)
2+3+4(5)
由例子就可以想到dp的过程了:
pos[num]数组代表num这个数字在之前出现的位置,状态转移方程:
dp[ i ] = dp[ i - 1 ] + num + ( i - pos[num] - 1 ) * num。
注意LL。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <cmath> #include <stack> #include <vector> #include <queue> #include <map> #define LL long long #define lson lo, mi, rt << 1 #define rson mi + 1, hi, rt << 1 | 1 using namespace std; const int maxn = 1e6 + 10; const int inf = 0x3f3f3f3f; const double eps = 1e-8; const double pi = acos(-1.0); const double ee = exp(1.0); int pos[maxn]; LL dp[maxn]; int main() { #ifdef LOCAL freopen("in.txt", "r", stdin); #endif // LOCAL int ncase; scanf("%d", &ncase); while (ncase--) { memset(pos, 0, sizeof(pos)); int n; scanf("%d", &n); dp[0] = 0; for (int i = 1; i <= n; i++) { int num; scanf("%d", &num); dp[i] = dp[i - 1] + num + num * (i - pos[num] - 1); pos[num] = i; } LL ans = 0; for (int i = 1; i <= n; i++) { ans += dp[i]; } printf("%lld\n", ans); } return 0; }
K:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5527
这是一道考英语考模拟的题目。
题目好长啊,但是读懂了模拟一下还是不难的。
题意:
首先输入ncase。
然后分别输入n,q,s,c,分别代表n个队伍,q台服务器,每个队伍初始分数s,以及检查时间点个数c。
然后再每个检查时间点,所知道的信息为:
共发生了a次攻击:
每次攻击分别输入fr, to, ser,代表 fr 队经由服务器 ser 攻击了 to 队;
被攻击成功的队伍的分数将减少 n - 1 分,攻击成功的队伍的分数增加的分数为 (n - 1 分 / 经过相同服务器攻击成功的队伍数)。
对于每台服务器:
统计每个队是否正常维护当前服务器,若否为0,是为1;
增减分数规则同上;
最后有k次询问,每次输出id为x的队伍的分数和排名。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <cmath> #include <stack> #include <vector> #include <queue> #include <map> #define LL long long #define lson lo, mi, rt << 1 #define rson mi + 1, hi, rt << 1 | 1 using namespace std; const int maxn = 100 + 10; const int inf = 0x3f3f3f3f; const double eps = 1e-6; const double pi = acos(-1.0); const double ee = exp(1.0); struct Team { int id, rank; double score; } team[maxn]; bool attack[maxn][maxn][maxn]; bool success[maxn]; bool cmp_score(Team a, Team b) { return a.score > b.score; } bool cmp_id(Team a, Team b) { return a.id < b.id; } int main() { #ifdef LOCAL freopen("in.txt", "r", stdin); #endif // LOCAL int ncase; scanf("%d", &ncase); while (ncase--) { int n, q, s, c; scanf("%d%d%d%d", &n, &q, &s, &c); for (int i = 0; i <= n; i++) { team[i].id = i; team[i].rank = 1; team[i].score = s; } while (c--) { int a; scanf("%d", &a); memset(attack, false, sizeof(attack)); while (a--) { int fr, to, ser; scanf("%d%d%d", &fr, &to, &ser); attack[fr][to][ser] = true; } for (int ser = 1; ser <= q; ser++) { for (int to = 1; to <= n; to++) { int cnt = 0; for (int fr = 1; fr <= n; fr++) { if (attack[fr][to][ser]) { cnt++; } } if (cnt == 0) continue; double sum = (n - 1) / double(cnt); team[to].score -= (n - 1); for (int fr = 1; fr <= n; fr++) { if (attack[fr][to][ser]) team[fr].score += sum; } } } for (int j = 0; j < q; j++) { memset(success, false, sizeof(success)); int cnt = 0; for (int k = 1; k <= n; k++) { int x; scanf("%d", &x); if (x) { success[k] = true; cnt++; } else { team[k].score -= (n - 1); } } double sum = (n - 1) / double(cnt); sum = sum * (n - cnt); for (int k = 1; k <= n; k++) { if (success[k]) { team[k].score += sum; } } } sort(team + 1, team + n + 1, cmp_score); for (int j = 1; j <= n; j++) { if (j != 1) { if (team[j - 1].score - team[j].score < eps) team[j].rank = team[j - 1].rank; else team[j].rank = j; } else team[j].rank = j; } sort(team + 1, team + n + 1, cmp_id); int k; scanf("%d", &k); while (k--) { int x; scanf("%d", &x); printf("%lf %d\n", team[x].score, team[x].rank); } } } return 0; }
总结:
首先感觉还是需要思维的题目有点吃力,之后的训练是多练思维,dp,很明显亮GG的思维就比我好太多。
接下来还是,好好练吧,希望一百多天后能实现自己的梦想。