[L,R]中具有奇数个奇数因子的数
Number of numbers in [L, R] with an odd number of odd factors
我正在做这个竞争性编程任务,尽管我认为我有一个渐近最优解,但我仍然超过了时间限制。你需要注册一个账户才能看到问题陈述并提交,所以我会在这里重述:
给定一个范围[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*平方。(或者找到前几个这样的数字并检查OEIS(
知道了这一点,我们就可以很容易地计算出O(1(中区间中这些数字的计数,这样我们就可以回答O(Q(中的所有查询。
-
首先计算范围[L,R],我们可以计算范围[0,R]-[0,L-1]
-
对于一些范围[0,X],我们可以注意到在这个区间中有sqrt(X(平方
-
类似于双平方,大约有sqrt(X/2(这样的数字
-
C++中大数字的Sqrt不是那么精确,所以我们可能需要添加一些+-1来计算中的Sqrt
示例代码(C++(:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll solve(ll x)
{
ll sq = sqrt(x)+2;
while(sq*sq > x)sq--;
ll sq2 = sqrt(x/2)+2;
while(2*sq2*sq2 > x)sq2--;
return sq + sq2;
}
ll solve(ll l, ll r)
{
return solve(r) - solve(l-1);
}
int main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
ll q,l,r,cs=1;
cin>>q;
while(q--)
{
cin>>l>>r;
cout<<"Case "<<cs++<<": "<<solve(l,r)<<"n";
}
}
相关文章:
- 没有找到相关文章