参加的最后一场校赛,明年大三就看着学弟学妹们打了,最后一年还是侥幸拿了个一等奖,两年一等奖美滋滋,运气大于实力。
A
Problem Description
meopass和ToRapture玩游戏,有nn堆石子,每堆石子有a_iai的重量。
两人轮流行动,ToRapture先手。每次ToRapture会拿若干堆总重量为奇数的的石子,而meopass会拿若干堆总重量为偶数的的石子,两个人都会采取最优行动策略,无法行动的人输。
meopass花了10分钟(天)完全了解这个游戏了,他知道了这个游戏的必胜方法,于是他自己带了很多很多的石子,想要在游戏开始前作弊,通过选取一些堆,在上面添加一些自己带来的石子,从而保持自己的必胜。
问他最少需要带多少石子才能保证自己的胜利?
Input
共TT次询问,每组样例第一行包含正整数nn,含义如上。
T = 10, 1 \leq n \leq 10^6, 1 \leq a_i \leq 10^9T=10,1≤n≤106,1≤ai≤109。
Output
对于每次询问输出一个答案,每个答案占一行。
Sample Input
1 2 2 1
Sample Output
1
A题:所以ToRapture是从 总质量为奇数的堆 中 选择若干堆拿走? 还是从 若干堆中拿走总质量为奇数的石子? 还是从所有堆中选择出 若干堆总质量为奇数的堆,然后把它们拿走?还是blablabla.....
出题人说我俩的语文老师不是同一个人...那当然不是同一个人啊,一道水题WA了三发,每一发都觉得自己读题是对的。最后AC。只需要把所有奇数堆的石子全部补成偶数就可以了。Orz。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+5;
int a[maxn];
int main()
{
int T, n;
scanf("%d", &T);
while(T--)
{
scanf("%d", &n);
int sum=0;
for(int i=0; i<n; i++)
{
scanf("%d", &a[i]);
if(a[i]%2==1) sum++;
}
printf("%d\n", sum);
}
}
B
Problem Description
meopass在101一不小心睡着了。
睡梦中的他进入了一个美丽的三维空间,空间里有nn个旅游景点,他们的位置为(x_i, y_i, z_i)(xi,yi,zi),景点间的距离是欧氏距离(欧几里得距离,例如二维的欧氏距离就是勾股定理)。
但是这nn个景点都是独立的,空间的主人希望他建一些桥梁,从而把这nn个景点连接起来,不然就永远把他囚禁在这里。每个桥梁连接两个不同的景点,桥梁的造价就是这两个景点间的距离。
问他需要花费的最少价钱是多少,因为花的太多的话空间的主人就会不高兴了QAQ。
Input
共TT次询问,每组样例第一行包含正整数nn,含义如上。
T = 5, 1 \leq n \leq 1000, -1000 \leq x_i, y_i, z_i \leq 1000T=5,1≤n≤1000,−1000≤xi,yi,zi≤1000。
Output
对于每次询问输出一个答案,每个答案占一行,保留小数点后两位有效数字。
Sample Input
1 2 1 1 1 2 2 2
Sample Output
1.73
B题:三维空间下的最小生成树问题,但是其实我们只需要O(n^2)处理出任意两点之间的距离就成了一个最小生成树的裸题了。开场看出题意懒得找板子一直没动,结果还拿了一血...Orz
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+5;
const int maxm = 1e3+5;
int pre[maxn];
int found(int x)
{
if(pre[x]==-1) return x;
else return pre[x] = found(pre[x]);
}
struct Node{
int x, y, z;
}node[maxm];
struct Edge{
double l;
int a, b;
bool operator <(const Edge &b)const{
return l<b.l;
}
}edge[maxn];
double getl(int i, int j)
{
double x = node[i].x - node[j].x;
double y = node[i].y - node[j].y;
double z = node[i].z - node[j].z;
return sqrt(x*x+y*y+z*z);
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
memset(pre, -1, sizeof pre);
int n, cnt = 0;
scanf("%d", &n);
for(int i=0; i<n; i++)
scanf("%d%d%d", &node[i].x, &node[i].y, &node[i].z);
for(int i=0; i<n; i++)
for(int j=i+1; j<n; j++)
{
edge[cnt].l = getl(i, j);
edge[cnt].a = i;
edge[cnt].b = j;
cnt++;
}
sort(edge, edge+cnt);
// for(int i=0; i<cnt; i++)
// printf("%f\n", edge[i].l);
int sum = 0;
double ans = 0;
for(int i=0; i<cnt; i++)
{
int u = edge[i].a;
int v = edge[i].b;
double w = edge[i].l;
int t1 = found(u);
int t2 = found(v);
if(t1!=t2)
{
ans += w;
pre[t1] = t2;
sum++;
}
if(sum==n-1) break;
}
printf("%.2f\n", ans);
}
}
C
Problem Description
axp非常喜欢一款技术性超强的抽卡赌博游戏,它改编自知名牌类游戏比大小。游戏开始时牌库中有3030张卡牌,开局先从牌库中抽33张牌,之后每回合可以抽一张牌(也就是说第一回合开始时,你实际上起了3+1=43+1=4张牌),然后再出一张牌。
牌库中有两种牌,每张牌都有一个价值:
1.1.随从牌,价值为v(1\leq v \leq1000)v(1≤v≤1000),使用一张价值为vv的卡牌会为你召唤一名随从,每回合这个随从都可以攻击敌人一次造成vv点伤害。在召唤出随从后,这名随从不能立刻攻击,需要等到下回合才可以第一次攻击敌人。
2.2.一种神奇的卡牌“右手第一张”。这种卡牌的价值为00,但使用这张卡牌之后,你会情不自禁地向敌人致敬:“抱歉”,同时直接对敌人造成10001000点伤害。
现在axp和meopass要在这款游戏中一决高下。axp担心会惨败,于是开了透视外挂看穿了牌库中的3030张牌。
请你帮axp制定出牌策略,使得meopass受到尽量多的伤害。
Input
第一行一个整数TT,代表数据组数。
接下TT组数据,每组数据一行3030个数,其中第ii个数代表牌库中第ii张卡牌的价值。
输入保证合法。
Output
输出4040回合后axp对meopass造成的伤害总和。
什么,你问卡抽完了怎么办?继续打呗=v=
每组数据输出一行,包含一个整数作为答案。
Sample Input
3 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
Sample Output
29039 735 29013
C题:一眼炉石的世界观,作为炉石传说玩家怎么可能不会这道题呢,直接模拟,贪心每回合打出手上攻击力最高的随从。如愿一些,不负传说之名。Orz
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+5;
int a[41];
int have[5];
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int sum = 0;
for(int i=0; i<30; i++)
scanf("%d", &a[i]);
for(int i=0; i<3; i++)
have[i] = a[i];
for(int i=3; i<30; i++)
{
have[3] = a[i];
sort(have, have+4);
if(have[3]==0) sum+=1000;
else sum += have[3]*(40-i+2);
}
for(int i=0; i<3; i++)
{
if(have[i]==0) sum+=1000;
else sum += have[i]*(10+i);
}
printf("%d\n", sum);
}
}
D
Problem Description
ToRapture在学习编程的时候发现Golang的package之间不能循环依赖。 例如在Golang中,若package A依赖package B,package B又依赖package A,则无法构建项目。 给出若干package之间的依赖关系,请你判断出能否成功构建项目。
Input
多组输入,每组的第一行为两个非负整数N,MN,M,表示共有NN个package和MM条依赖关系, 接下来的一行为NN个只由大小写字母组成的互不相同的字符串p_1, p_2 \cdots p_np1,p2⋯pn,每个字符串p_ipi最多16个字符,字符串间用空格分割。 接下来的MM行,每行两个字符串p_i, p_jpi,pj,表示p_ipi依赖p_jpj。 \sum N \le 10^5, \sum M \le 5 \times 10^5∑N≤105,∑M≤5×105
Output
对于每组数据,若可以成功构建,即没有循环依赖,则输出一行"Citrus Saikou!",否则输出一行"DameDameYo",输出双引号内的内容。
Sample Input
4 5 mei yuzu matsuri harumi mei yuzu harumi yuzu harumi mei matsuri mei matsuri harumi 5 4 A B C D E B A C A D B E C 3 1 str os sys os str 4 4 socket redis kv data redis socket kv redis data kv redis data
Sample Output
Citrus Saikou! Citrus Saikou! Citrus Saikou! DameDameYo
D题:用map处理String和int之间的对应关系,然后就变成了一个有向图判环的问题。有向图判环用拓扑排序也好,什么连通性算法也好,floyd能不能判有向图的环我都忘了,场上真的是一脸懵逼,于是就鸵了一段时间,最后没办法码了一发DFS染色判环过的,Orz
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
map<string, int>s;
int vis[maxn], rd[maxn];
bool huan = false;
int cnt;
void dfs(vector<int >v[], int x, int val)
{
//printf("%d: %d\n", x, val);
for(int i=0; i<v[x].size(); i++)
{
if(vis[v[x][i]] == val){
//printf("**%d %d\n", x, v[x][i]);
huan = true;
return ;
}
else {
vis[v[x][i]] = val;
dfs(v, v[x][i], val);
vis[v[x][i]] = 0;
}
}
}
int main()
{
int n, m;
string str, s1, s2;
while(cin>>n>>m)
{
vector<int >v[maxn];
memset(vis, -1, sizeof vis);
huan = false;
s.clear();
//biaohao
for(int i=0; i<n; i++)
{
cin>>str;
s.insert(make_pair(str, i));
}
//jianbian
for(int i=0; i<m; i++)
{
cin>>s1>>s2;
v[s[s1]].push_back(s[s2]);
//printf("#%d %d\n", s[s1], s[s2]);
}
int p=1;
for(int i=0; i<n; i++)
{
if(vis[i]==-1)
dfs(v, i, p++);
}
// for(int i=0; i<n; i++)
// {
// printf("%d %d\n", i, vis[i]);
// }
if(huan) puts("DameDameYo");
else puts("Citrus Saikou!");
}
}
E
meopass日常在赛场上摸鱼,并且感慨人生,做不出题目的他一边回忆昨晚吃的烧烤的味道,一边期待着今晚的火锅,随着时间的推移,赛场上过题目的人越来越多,他觉得自己不能再这么颓废下去了,所以他决定:"数气球吧..."
已知现在赛场上共3种颜色的气球,分别是"Red", "Green", "Yellow",分别用'R', 'G', 'Y'来代表。一般而言,赛场上过的最多的题目就是签到题,现在给出赛场上每只队伍的过题情况,你能知道签到题对应的气球是什么颜色吗?
Input
共TT次询问,每组样例第一行包含正整数nn,代表场上的队伍数,接下来n行用一个仅包含'R', 'G', 'Y'的字符串表示,代表这个队伍现在拥有哪些气球,每支队伍都不会有重复的气球,签到题可能不唯一。
T = 100, 1 \leq n \leq 10T=100,1≤n≤10.
Output
对于每次询问输出一个或多个字符串,多个的情况下按字典序升序输出,表示签到题对应的气球的颜色,每个答案占一行。
Sample Input
1 2 GRY YR
Sample Output
Red Yellow
E题:开场的水题判一下字符串计数然后判一下最大输出就可以。用first判断单词前需不需要加空格就可以了。运气好拿了个一血。Orz
F
Problem Description
meopass的面前有n个精灵球,虽然他不知道这里面分别装着哪些精灵,但是他知道他们的等级分别是多少,第i个精灵球的等级是v_ivi, vv是一个11
到nn的全排列。
现在他希望从左往右选择kk个精灵球p_1, p_2, \dots, p_kp1,p2,…,pk,满足1 \leq p_1 < p_2 < \dots < p_k \leq n1≤p1<p2<⋯<pk≤n,且精灵球的等级递增。
meopas并不关心kk有多大,他只想知道有多少种选择的方案。
Input
共TT次询问,每组样例第一行包含正整数nn,代表nn个精灵球的等级。
T = 10, 1 \leq n \leq 100000T=10,1≤n≤100000。
Output
每次询问输出结果占一行,输出答案对100000007100000007取模的结果。
Sample Input
1 2 1 2
F题:F就非常的有意思了,去年校赛就有一个一模一样的求非降(这次是严格上升)子序列的个数,当时现场推的觉得自己巨牛叉,然后下来之后大佬轻飘飘一句这个就是个dp啊觉得自己这么弱怎么还好意思沾沾自喜(当时根本不知道什么事dp)。然后今年这个题开场想了无数种优化办法,最后发现是线段树区间查询就过了....巨弱一开始都没有想到,还手写了一个lazy标记打算区间修改,码了一半发现自己跑偏了...最后因为没有加取模WA了两发,Orz。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+5;
const int mod = 100000007;
int a[maxn];
struct Node{
int l, r;
int lazy;
int sum;
}node[maxn];
void init(int n)
{
node[1].l = 1;
node[1].r = (1<<n);
node[1].sum = 0;
for(int i=2; i<(1<<(n+1)); i++)
{
if(i%2==0){
node[i].l = node[i/2].l;
node[i].r = node[i/2].l+(node[i/2].r-node[i/2].l+1)/2-1;
node[i].sum = 0;
}
else {
node[i].l = node[i/2].l+(node[i/2].r-node[i/2].l+1)/2;
node[i].r = node[i/2].r;
node[i].sum = 0;
}
}
return;
}
int ask(int l, int r, int i)
{
if(node[i].l==l && node[i].r==r) return node[i].sum;
if(node[i*2].r < l) {
return ask(l, r, i*2+1);
}
if(node[i*2+1].l > r) {
return ask(l, r, i*2);
}
return ask(l, node[i*2].r, i*2) + ask(node[i*2+1].l, r, i*2+1);
}
int found(int i, int x)
{
if(node[i].l==node[i].r)
return i;
if(x>node[i*2].r) return found(i*2+1, x);
return found(i*2, x);
}
void add(int x, int val)
{
int p = found(1, x);
node[p].sum = (node[p].sum + val)%mod;
while(p!=1)
{
p = p/2;
node[p].sum = (node[p].sum + val)%mod;
}
return ;
}
int main()
{
int T, n;
scanf("%d", &T);
while(T--)
{
scanf("%d", &n);
int topp = 0;
int m = n-1;
while((m>>topp)>0) topp++;
//printf("top:%d\n", topp+1);
init(topp);
for(int i=0; i<n; i++)
scanf("%d", &a[i]);
for(int i=0; i<n; i++)
{
int num = ask(1, a[i], 1);
//printf("**%d: %d\n", a[i], num);
add(a[i], num+1);
}
// for(int i=1; i<(1<<(topp+1)); i++)
// {
// printf("%d: %d %d %d\n", i, node[i].l, node[i].r, node[i].sum);
// }
printf("%d\n", node[1].sum%mod);
}
}
因为是用模拟的思路手敲的线段树,然后第二天就被学妹锤脸拿出了一个更加优美的线段树,拿出来以供自己学习。Orz
struct ss
{
int l;
int r;
int num;
} segt[maxn];
void build(int i,int l,int r)
{
segt[i].l=l;
segt[i].r=r;
if(l==r)
{
segt[i].num=num[l];
return;
}
int mid=(r+l)/2;
build(i*2,l,mid);
build(i*2+1,mid+1,r);
segt[i].num=segt[2*i].num+segt[2*i+1].num;
}
void add(int i,int t,int b)
{
segt[i].num+=b;
if(segt[i].l==t&&segt[i].r==t)
{
//segt[i].num+=b;
return;
}
int mid=(segt[i].r+segt[i].l)/2;
if(t<=mid)
add(2*i,t,b);
else
add(2*i+1,t,b);
}
int query(int i,int l,int r)
{
if(segt[i].r==r&&segt[i].l==l)
return segt[i].num;
int mid=(segt[i].l+segt[i].r)/2;
if(r<=mid)
query(2*i,l,r);
else if(l>mid)
return query(i*2+1,l,r);
else
return query(i*2,l,mid)+query(i*2+1,mid+1,r);
}
I
meopass认为字符串的滑稽度等于它里面所有字母的滑稽度之和。每个字母的滑稽度可以由你来分配,不同字母的滑稽度不同,分别对应一个11-2626之间的整数。
他不在乎字母大小写,也就是说字母AA和aa的滑稽度相同。
给定一个字符串,输出它的最大可能的滑稽度。
例如:daddad,你可以将2626分配给dd,2525分配给aa,这样整个字符串滑稽度为7777。
Input
数据包含多组样例,处理到文件尾。
输入一个字符串S, |S| \leq 10000S,∣S∣≤10000,S中没有除字母外的其他字符。
Output
由你将11-2626分配给不同的字母,使得字符串S的滑稽度最大,输出这个滑稽度。
Sample Input
Dad
Sample Output
77
I题:签到用的水题,一开始没注意多组样例WA了一发,只需要对26个数字计数然后排序然后计算就可以了。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e4+5;
char a[maxn];
int cnt[50];
int main()
{
while(scanf("%s", a)!=EOF)
{
int lena = strlen(a);
memset(cnt, 0, sizeof cnt);
for(int i=0; i<lena; i++)
{
if(a[i]>='a' && a[i]<='z') a[i]-=32;
//printf("%c", a[i]);
cnt[a[i]-'A'+1]++;
}
int sum = 0;
sort(cnt+1, cnt+27);
for(int i=26; i>0; i--)
{
//printf("%d: %d\n", i, cnt[i]);
sum += i*cnt[i];
}
printf("%d\n", sum);
}
}
这次过题的顺序是 E->I->A->C->B->D->F。其中E开场一血后看有人过了A题想着没有一血拿了就去开I题,结果I题judge有问题连WA三发,然后扭回头去看A题又搞不懂出题人的意思又不知道怎么做又WA了两发,然后心态就崩掉了。这个时候被告知I题rejudge,A题再莽两发终于搞懂题意AC,三题后暂居榜首(一位老学长这个时候被打了星hhh)CBD三题连续1A过,然后和场上一群人一起在啃F题,想到数据结构想到线段树模拟遂过。没有被长理锤得太惨还是比较开心的,最后四题一血侥幸拿一等奖还是很开心的,校赛的退役之战hhh。同时向不知名大佬低头,全场被压一点脾气都没有Orz