第一次类似组队那样练题,做到后期感觉自己还是后劲不足,难题还是做不来。
下午做出了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的思维就比我好太多。
接下来还是,好好练吧,希望一百多天后能实现自己的梦想。