[L,R]中具有奇数个奇数因子的数

Number of numbers in [L, R] with an odd number of odd factors

本文关键字:      更新时间:2023-10-16

我正在做这个竞争性编程任务,尽管我认为我有一个渐近最优解,但我仍然超过了时间限制。你需要注册一个账户才能看到问题陈述并提交,所以我会在这里重述:

给定一个范围[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(中的所有查询。

  1. 首先计算范围[L,R],我们可以计算范围[0,R]-[0,L-1]

  2. 对于一些范围[0,X],我们可以注意到在这个区间中有sqrt(X(平方

  3. 类似于双平方,大约有sqrt(X/2(这样的数字

  4. 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";
}
}
相关文章:
  • 没有找到相关文章