题目大意
给出 n n n,求 ( n m o d 1 ) o r ( n m o d 2 ) o r ( n m o d 3 ) o r … o r ( n m o d ( n − 1 ) ) o r ( n m o d n ) (n\mod 1)\ or(n\mod2)\ or(n\mod 3)\ or\dots or\ (n\mod (n-1)) \ or(n\mod n) (nmod1) or(nmod2) or(nmod3) or…or (nmod(n−1)) or(nmodn)。
Solution
对于一个 n n n,从 ⌊ n 2 ⌋ + 1 \lfloor\frac{n}{2}\rfloor+1 ⌊2n⌋+1 开始,余数就形成一个公差为 1 的等差数列。因此最后的答案肯定是 2 x − 1 2^x-1 2x−1。
考虑找出 x x x 。而 x x x 取决于 ⌊ n + 1 2 ⌋ − 1 \lfloor\frac{n+1}{2}\rfloor-1 ⌊2n+1⌋−1,因为等差数列的首项是它。首项在二进制下的位数就是 x x x。
因此有不等式: ⌊ n + 1 2 ⌋ − 1 ≥ 2 x − 1 \lfloor\frac{n+1}{2}\rfloor-1\ge2^{x-1} ⌊2n+1⌋−1≥2x−1,而目的就是求出最大的 x x x。
预处理出 2 i 2^i 2i,然后找到最大的 x x x 满足上式,期间一直加上 2 x 2^x 2x 即可。
Code
#include<cstdio>
using namespace std;
#define ll long long
#define G getchar()
ll T, n, l, len, ans, pow[50];
inline ll read()
{
ll an = 0, ch = G;
for (; ch < 48 || ch > 57 ; ch = G);
for (; ch > 47 && ch < 58 ; ch = G)
an = (an << 3) + (an << 1) + ch - 48;
return an;
}
int main()
{
T = read();
pow[0] = 1;
for (ll i = 1 ; i <= 40 ; i++)
pow[i] = pow[i - 1] << 1;
while (T--)
{
n = read();
l = n / 2 + 1;
len = n - l;
ans = 0;
for (ll i = 0 ; pow[i] <= len ; i++)
ans += pow[i];
printf("%lld\n", ans);
}
return 0;
}