A Friends Meeting
题意:有两个人在数轴上的不同位置,现在他们需要到一个位置碰面。每次每人只能向左或向右走1个单位,轮流进行。每个人第一次走时疲劳度+1,第二次走时疲劳度+2,以此类推。问两个人碰面时总的疲劳度最小为多少?
思路:碰面位置为(a+b)/2.
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 using namespace std; 5 int main() 6 { 7 int a,b; 8 scanf("%d%d", &a, &b); 9 long long ans = 0; 10 int mid = (a + b) / 2; 11 ans += (1 + abs(mid - a))*abs(mid - a) / 2 + (1 + abs(mid - b))*abs(mid - b) / 2; 12 printf("%I64d ", ans); 13 return 0; 14 }
B World Cup
题意:有n只球队编号为1~n,每轮从编号小的开始,选择编号比其大的最小的编号的球队比赛。问想要编号为a和b的球队进行比赛,最好情况会在第几轮?(假设在遇见之前能打败其他队伍)
思路:如果编号分别在n/2两侧,那么肯定在最后一轮碰面,否则,肯定在这之前碰面。
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 using namespace std; 5 int main() 6 { 7 int n, a, b; 8 scanf("%d%d%d", &n, &a, &b); 9 if (a > b) a = a ^ b, b = a ^ b, a = a ^ b; 10 int rounds = log2(n); 11 int total = rounds; 12 while (rounds >= 1) 13 { 14 int tmp = n / 2; 15 if (a <= tmp && b > tmp) break; 16 else if (b <= tmp) n = tmp; 17 else 18 { 19 n -= tmp; 20 a -= tmp; 21 b -= tmp; 22 } 23 rounds--; 24 } 25 if (rounds == total) printf("Final! "); 26 else printf("%d ", rounds); 27 return 0; 28 }
C Laboratory Work
题意:有n个整数,最大和最小之差不超过2.现在让你构建一个含有n个整数的集合,其平均值和已给出的集合的平均值相同,同时最小值不超过已知最小,最大值不超过已知最大。求构建的集合和原来已知中相同的数目最小为多少?
思路:要使个数为n,且平均值还想相同,由于极差不超过2,则a,a+1,a+2的个数已知,并且只能用2个a+1替换a与a+2.
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 using namespace std; 5 const int maxn = 100010; 6 int X[maxn],Num[4]; 7 int main() 8 { 9 int n; 10 scanf("%d", &n); 11 int Min = maxn; 12 for (int i = 1; i <= n; i++) scanf("%d", &X[i]),Min=min(Min,X[i]); 13 for (int i = 1; i <= n; i++) Num[X[i] - Min]++; 14 int n1 = Num[0] + Num[2] + Num[1] % 2; 15 int n2 = n - 2 * min(Num[0], Num[2]); 16 if (n1 <= n2&&Num[2]>0&&Num[1]>0) 17 { 18 Num[0] += Num[1] / 2; 19 Num[2] += Num[1] / 2; 20 Num[1] -= 2*(Num[1] / 2); 21 printf("%d ", n1); 22 } 23 else 24 { 25 int tmp = min(Num[0], Num[2]); 26 Num[0] -= tmp; 27 Num[1] += 2 * tmp; 28 Num[2] -= tmp; 29 printf("%d ", n2); 30 } 31 bool isfirst = true; 32 for (int i = 0; i <= 2; i++) 33 { 34 while (Num[i]--) 35 { 36 if (isfirst) isfirst = false,printf("%d",i+Min); 37 else printf(" %d", i + Min); 38 } 39 } 40 printf(" "); 41 return 0; 42 }
D Peculiar apple-tree
题意:有一颗苹果树,一年结一次果。苹果成熟时,每过一秒,第i个苹果会落到第Pi个苹果最初的位置(i>1),当有多个苹果同时落在一个位置时,每有两2个则相互湮灭。现在在第1个苹果的位置收苹果,问最后能够收到多少?
思路:建树,确定每个苹果所在的层次,同一层的苹果肯定最后会一同落在根上或是其他结点。判断每层苹果的奇偶数即可。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<vector> 5 #include<cstring> 6 using namespace std; 7 const int maxn = 100010; 8 struct edge 9 { 10 int to, next; 11 edge(int tt=0,int nn=0):to(tt),next(nn){} 12 }Edge[maxn*2]; 13 int Head[maxn],totedge,ans=0; 14 bool vis[maxn]; 15 int Lvl[maxn],maxlevel; 16 void AddEdge(int from, int to) 17 { 18 Edge[totedge] = edge(to, Head[from]); 19 Head[from] = totedge++; 20 Edge[totedge] = edge(from, Head[to]); 21 Head[to] = totedge++; 22 } 23 void getAns(int st,int level) 24 { 25 vis[st] = true; 26 for (int i = Head[st]; i != -1; i = Edge[i].next) 27 { 28 int to = Edge[i].to; 29 if (!vis[to]) 30 { 31 getAns(to, level + 1); 32 Lvl[level]++; 33 if (level > maxlevel) maxlevel = level; 34 } 35 } 36 } 37 int main() 38 { 39 ans = 0; 40 totedge = 0; 41 memset(Head, -1, sizeof(Head)); 42 memset(vis, 0, sizeof(vis)); 43 int n; 44 scanf("%d", &n); 45 for (int i = 2; i <= n; i++) 46 { 47 int to; 48 scanf("%d", &to); 49 AddEdge(i, to); 50 } 51 Lvl[1] = 1; 52 maxlevel = 2; 53 getAns(1,2); 54 for (int i = 1; i <= maxlevel; i++) if (Lvl[i] % 2) ans++; 55 printf("%d ", ans); 56 return 0; 57 }
E Game with String
题意:A构造一个字符串s1,并将其前k个循环左移得到s2.B现在知道s1,可以询问B在s2中的第一个字符和另一个位置上的字符为多少,如果能够唯一确定,则B赢。求B赢的最大概率?
思路:首先得到所有子串的个数(只需确定起始字符和终止字符以及字符数)。然后枚举第一个字符、字符数和第二个字符,如果只出现一次,则记录。
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 int Num[27][27][5010]; 8 char str[5010 * 2]; 9 int main() 10 { 11 scanf("%s", str + 1); 12 int len = strlen(str + 1); 13 for (int i = 1; i <= len; i++) str[len + i] = str[i]; 14 str[len * 2 + 1] = '