XTU-OJ 《C语言程序设计》 1308-比赛

文章描述了一种比赛规则,每轮比赛基于2的幂次淘汰选手,直至决出冠军。解题思路涉及找到最接近m的2的幂次k,并通过打表方法优化查找过程。AC代码展示了C语言的解决方案,通过循环和数组来计算比赛的轮数和场数。

题目描述

有n个人要进行比赛,比赛规则如下:

  1. 假设每轮比赛的人是m,取最大的k,k=2^t且k≤m。这k个人每2人举行一场比赛,胜利者进入一下轮,失败者被淘汰。

  2. 余下的m-k个人,不进行比赛,直接进入下一轮

  3. 直到决出冠军,比赛结束。

比如有5个人参加比赛,第一轮举办2场,剩余3人进入第二轮,第二轮1场,剩余2人进入第三轮,第三轮举办1场决出冠军,所以一共要办4场比赛。 请问一共要举行几轮多少场比赛?

输入

第一行是一个整数K,表示样例的个数。 以后每行一个样例,为n(1≤n≤1000000000)

输出

每行输出两个整数,轮数和比赛场数,中间用一个空格隔开。

样例输入

 2
 1
 5

样例输出

 0 0
 3 4

解题思路:本题只要题目意思读懂,思路就出来了。

每轮 找到 k 的值,然后进行 k/2 场比赛, 淘汰 k/2 个人, 还剩下 m - k/2 个人, 进入下一轮。循环往复,直到决出第一名(剩下最后一人)。

记录好 循环的轮数 和 比赛的场数,答案轻松得出。

怎么简单方便的找到最接近 m 的 k ? 笔者的方法是进行打表,先把2^x 的值 依次存入 数组中。之后就可以在数组表里比较查找出这个k啦。

AC代码:

#include <stdio.h>

int main()
{
    int pow2[35] = {1,2};
    int K,m,s,i = 1;
    int cnt,num;					// cnt 是比赛轮数,num 是 比赛场数
    while (pow2[i] < 1e9)           // 打表
    {
        i ++;
        pow2[i] = 2*pow2[i-1];
    }

    scanf("%d",&K);
    while ( K --)
    {
        scanf("%d",&m);
        cnt = num = 0;
        while ( m != 1)             // 循环决出冠军
        {
            for ( i = 0; pow2[i] <= m; i ++);   // 找到最接近m的k
            s = i-1;                // 因为for循环性质, k = 2^s 才是最接近m的
                                    // 2^i 已经 >  m
            cnt ++, num += pow2[s]/2;
            m = m-pow2[s]/2;		
        }
        printf("%d %d\n",cnt,num);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值