题目大意:给定n,b,p,其中n为进行比赛的人数,b为每场进行比赛的每一位运动员需要的水的数量,
p为整个赛程提供给每位运动员的毛巾数量,
每次在剩余的n人数中,挑选2^k=m(m <=n)个人进行比赛,剩余的n-m个人直接晋级,
直至只剩一人为止,问总共需要的水的数量和毛巾的数量
解题思路:毛巾数很简单: n*p即可
水的数量:1,2,4,8,16,32,64,128,256,512,提前打成一个表,
根据当前剩余的人数n在表中二分查找最大的小于等于n的数,结果即为本次进行比赛的人数,记为a[pos]
根据a[pos]计算相应的水的数量,并用n-a[pos]/2(淘汰人数)以进行下一轮的计算,直至n为1
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
/* CF 628A --- Tennis Tournament --- 水题 */ #include <cstdio> #include <algorithm> using namespace std; int a[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 }; //在a的{x,y)中查找小于等于key的第一个位置 int BinarySearch(int x, int y, int key){ while (x < y){ int mid = x + (y - x) / 2; if (a[mid] <= key && a[mid + 1] > key){ return mid; } else if (a[mid] > key){ y = mid; } else{ x = mid+1; } } return -1; } int main() { #ifdef _LOCAL freopen("D:input.txt", "r", stdin); #endif int n, b, p; while (scanf("%d%d%d", &n, &b, &p) == 3){ int sum = 0; int t = n; while (t != 1){ //查找当前t个人需要多少人进行比赛 int pos = BinarySearch(0, 9, t); //a[pos]即为比赛人数的 a[pos]/2为裁判数 sum += (a[pos] * b + a[pos] / 2); t -= (a[pos] / 2); //减去淘汰的a[pos]/2即为剩余人数 } printf("%d %d\n", sum, n*p); } return 0; }