我正在做这个 竞赛编程任务,尽管我认为我的解决方案渐进地是最佳的,但我仍然遇到了超时问题。您需要注册帐户才能查看问题陈述并提交,因此我将在此重申:
给定范围[L,R],找到该范围内具有奇数个奇约数的整数数量。
限制条件为1 <= L <= R <= 10 ^ 18,并且有高达10 ^ 5个这样的查询。
例子:
[1,18]
的解决方案为7,因为在该范围内有7个具有奇数个奇约数的数字:
1 - (1)
2 - (1, 2)
4 - (1, 2, 4)
8 - (1, 2, 4, 8)
9 - (1, 3, 9)
16 - (1, 2, 4, 8, 16)
18 - (1, 2, 3, 6, 9, 18)
我的代码和想法:
我们知道除数成对出现,因此任何具有奇数个约数的奇数必须是平方数。任何具有奇数个约数的偶数必须具有某些具有奇数个约数的奇数“基数”,为了使这个“基数”能够做到这一点,它必须像之前讨论的那样是一个平方数。
本质上,我们正在寻找形式为O^2 * 2^N
的数字,其中O
是某个奇数。我将[L,R]
的解决方案视为[1,R] - [1,L)
,然后迭代所有2^N
并获取可以适合该数字下的O
的数量。
# include <bits/stdc++.h>
using namespace std;
typedef long long ll;
// number of numbers matching criteria on [1, n]
ll n_under(ll n){
ll res = 0;
while(n){
res += (sqrt(n) + 1ll)/2ll;
n /= 2ll;
}
return res;
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int q;
cin >> q;
for(int i = 1; i <= q; ++i){
ll l, r;
cin >> l >> r;
cout << "Case " << i << ": " << (n_under(r) - n_under(l - 1)) << endl;
}
return 0;
}
我在第一个测试集中遇到了TLE问题,但不确定原因。我正在寻找任何渐近改进或常数优化。
2
、4
和8
不是解的一部分,因为它们也有奇数个奇约数? - Wander3rres += (sqrt(n) + 1ll)/2ll
怎么解释?我不太理解。 - lincr