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]的奇数个数方法为:
- 设a和b之间有t个数,t = b - a -1。
- 如果a b都是奇数,答案为t / 2 + 2
- 如果a b都是偶数,答案为t / 2 + 1
- 如果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;
}