ABC293 F - Zero or One

题意

TT 组数据,每组一个正整数 nn,保证 2n10182\leq n \leq 10^{18} ,对于每个 nn 求满足条件的 bb 的个数,使得 nnbb 进制表示只包含 0011

思路

官方题解给出了一种正经的做法,这里给出一种简单的数据分治做法

对于每个数 nn ,考虑将对答案的贡献分为以下三类:

  1. n1n-1 , nn

    显然这两种情况下的表示分别为 10, 11

  2. 位数 3\leq 3

    1. 位数为 22 时可以在 n\sqrt{n} 的周围暴力枚举约 10001000
    2. 位数为 33 时同理在 n3\sqrt[3]{n} 周围暴力枚举
  3. 枚举进制 bb ,暴力检查

时间复杂度:

情况1: O(1)O(1)
情况2: O(1000logn)O(1000*\log{n})
情况3: O(n4)O(\sqrt[4]{n})

显然不会超时

警示后人

不要用 pow !!!不要用 pow !!!不要用 pow !!!不要用 pow !!!不要用 pow !!!不要用 pow !!!不要用 pow !!!不要用 pow !!!不要用 pow !!!不要用 pow !!!

这东西贼不稳定!

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/*
Name:
Author: xiaruize
Date:
*/
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define ull unsigned long long
#define ALL(a) (a).begin(), (a).end()
#define pb push_back
#define mk make_pair
#define pii pair<int, int>
#define pis pair<int, string>
#define sec second
#define fir first
#define sz(a) int((a).size())
#define rep(i, x, y) for (int i = x; i <= y; i++)
#define repp(i, x, y) for (int i = x; i >= y; i--)
#define Yes cout << "Yes" << endl
#define YES cout << "YES" << endl
#define No cout << "No" << endl
#define NO cout << "NO" << endl
#define debug(x) cerr << #x << ": " << x << endl
#define double long double
const int INF = 0x3f3f3f3f;
const int MOD = 1000000007;
const int N = 2e5 + 10;

// bool st;
int t;
int n;
// bool en;

bool check(int x, int k)
{
while (x)
{
if (x % k > 1)
return false;
x /= k;
}
return true;
}

int get(int x)
{
int l = 1, r = 1e6;
while (l < r)
{
int mid = l + r + 1 >> 1;
if (mid * mid * mid <= x)
l = mid;
else
r = mid - 1;
}
return l;
}

void solve()
{
cin >> n;
if (n == 2)
{
cout << "1" << endl;
return;
}
int x = sqrt(n);
int y = get(n);
int res = 0;
for (int i = 2; i <= 1e5 && i * i * i * i <= n; i++)
{
if (check(n, i))
res++;
}
for (int i = max(2ll, x - 1000); i <= min(x + 1000, n - 2); i++)
{
if (i * i + i + 1 == n || i * i + 1 == n || i * i + i == n || i * i == n)
res++;
}
for (int i = max(2ll, y - 1000); i <= min(y + 1000, n - 2); i++)
{
if (i * i * i + i * i + i + 1 == n || i * i * i + i * i + 1 == n || i * i * i + i * i + i == n || i * i * i + i * i == n || i * i * i + i + 1 == n || i * i * i + 1 == n || i * i * i + i == n || i * i * i == n)
res++;
}
cout << res + 2 << endl;
}

signed main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
// cerr<<(&en-&st)/1024.0/1024.0<<endl;
// auto t_1=chrono::high_resolution_clock::now();
cin >> t;
while (t--)
solve();
// auto t_2=chrono::high_resolution_clock::now();
// cout <<". Elapsed (ms): " << chrono::duration_cast<chrono::milliseconds>(t_2 - t_1).count() << endl;
return 0;
}