题目大意
我们定义满足下面条件的整数 X X X 为"好整数":
- 存在一个 正整数 对 ( a , b ) (a,b) (a,b) 使得 X = 2 a ⋅ b 2 X=2^a\cdot b^2 X=2a⋅b2。
给定一个正整数 N N N( 1 ≤ N ≤ 1 0 18 1\le N\le 10^{18} 1≤N≤1018),求 1 ∼ N 1\sim N 1∼N 中有多少"好整数"。
思路
下面是一张表格,第一列的数表示 a a a 的值,第一行表示 b b b 的值,第 x x x 列第 y y y 行的数表示 2 x ⋅ y 2 2^x\cdot y^2 2x⋅y2 的值。
a \ b | 1 | 2 | 3 | 4 |
---|---|---|---|---|
1 | 2 | 8 | 18 | 32 |
2 | 4 | 16 | 36 | 64 |
3 | 8 | 32 | 72 | 128 |
4 | 16 | 64 | 144 | 256 |
观察可得, 2 1 × 4 2 = 2 3 × 2 2 , 2 2 × 4 2 = 2 4 × 4 2 2^1\times 4^2=2^3\times2^2,\ 2^2\times4^2=2^4\times 4^2 21×42=23×22, 22×42=24×42,这的确是交换率的体现,但是我们仔细思考会发现,当 b b b 是二的倍数的时候,无论 a a a 取多少,都会有另一对 ( a ′ , b ′ ) (a',b') (a′,b′) 满足 2 a ′ ⋅ b ′ 2 = 2 a ⋅ b 2 2^{a'}\cdot {b'}^2=2^a\cdot b^2 2a′⋅b′2=2a⋅b2。
那么我们可以基于这个规律来减少枚举次数:枚举 b b b 的值,只需要枚举 1 ∼ ⌊ N ⌋ 1\sim \left \lfloor \sqrt{N}\right \rfloor 1∼⌊N ⌋ 的所有 奇数 ;然后枚举所有满足 2 a ⋅ b 2 ≤ N 2^a\cdot b^2\le N 2a⋅b2≤N 的 a a a。这种做法不但快捷,还可以保证不重不漏,可以在规定时间内输出正确的答案。
代码
赛时提交记录(含有一些多余内容):Submission #64615650。
cpp
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
LL n, ans;
int main()
{
cin >> n;
for (LL i = 2; i <= n; i *= 2) ans++;
for (LL i = 3; i * i * 2 <= n; i += 2)
for (LL j = 2; i * i * j <= n; j *= 2)
ans++;
cout << ans << endl;
return 0;
}
总结
这是一道数学思维题,难度与比赛分值 350 分相符。希望这篇题解对你有帮助,如有想法欢迎在评论区提出!