2021中国大学生程序设计竞赛(CCPC)- 网络选拔赛 1001 Cut The Wire

4 篇文章 0 订阅
3 篇文章 0 订阅

1001 Cut The Wire

Problem Description

In the country of Infinity , there is a strange road. This road only has a starting point, but no end. Since this road is infinite, there are also countless street lights. The street lights are numbered from 1(the starting point) to infinity. The street lights are connected by wires under a strange law:

For a street light x,

if x is even, then x is connected with x2 by a wire;

if x is odd, then x and 3x+1 is connected by a wire.

Now Kris is standing in the middle of street light n and n+1, and he is able to cut all wires passing by. That is, he will cut all wires connecting street lights a and b satisfying a≤n and b>n.

Now he wonders, how many wires he will cut. Please help him calculate.

Input

This problem contains multiple test cases.

The first line contains an integer T(1≤T≤10^5) indicating the number of test cases.

The next T lines each contains one integer n(1≤n≤10^9).

Output

For each test case, output one line of one integer indicating the answer.

Sample Input

2
12
60

Sample Output

10
50

题目大意:

有编号为1到正无穷的路灯,设路灯的编号为x。

如果x为奇数,那么x和3*x + 1用电线连接;如果x为偶数,那么x和x / 2用电线连接。

问在路灯n和路灯n + 1之间有多少根电线。

题解:

对于样例,如果我们站在路灯12和13中间,那么会有奇数11,9,7,5和偶数14,16,18,20,22,24一共十个数的电线经过路灯12和13之间。

所以对于任意路灯n和路灯n + 1之间的电线数量就等于区间((n-1)/3, n]的奇数个数加上区间[n+1, n*2]的偶数个数。

计算区间[a, b]的奇数个数方法为:

  1. 设a和b之间有t个数,t = b - a -1。
  2. 如果a b都是奇数,答案为t / 2 + 2
  3. 如果a b都是偶数,答案为t / 2 + 1
  4. 如果a b一奇一偶 ,答案为t / 2 + 1

计算偶数个数只需要交换步骤2,3的答案即可。

AC代码:

#include <iostream>
using namespace std;
typedef long long ll;
ll countOdd(ll a, ll b) { // 计算[a, b]区间内奇数个数 
    if (a == b) {
        if (a % 2 == 1) return 1;
        else return 0;
    }
    ll t = b - a - 1; // a和b之间有t个数 
    a = a % 2; b = b % 2;
    ll res = 0;
    if (a && b) res = t / 2 + 2; // a b都是奇数 
    else if (!a && !b) res = t / 2 + 1; // a b都是偶数 
    else res = t / 2 + 1; // a b一奇一偶 
    return res;
}
ll countEven(ll a, ll b) { // 计算[a, b]区间内偶数个数 
    if (a == b) {
        if (a % 2 == 1) return 0;
        else return 1;
    }
    ll t = b - a - 1; // a和b之间有t个数 
    a = a % 2; b = b % 2;
    ll res = 0;
    if (a && b) res = t / 2 + 1; // a b都是奇数 
    else if (!a && !b) res = t / 2 + 2; // a b都是偶数 
    else res = t / 2 + 1; // a b一奇一偶 
    return res;
}
int main() {
    ll t;
    scanf("%lld", &t);
    while (t --) {
        ll n;
        scanf("%lld", &n);
        ll res = countOdd((n - 1) / 3 + 1, n) + countEven(n + 1, n * 2);
        printf("%lld\n", res); // 答案为( (n-1)/3, n]的奇数个数加[n+1, n*2]的偶数个数 
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值