E - 2^a b^2 Editorial by Binary_64

Solution for Problem C

So far, there is no English solution for this problem, so I wrote one.

Below are two different approaches to solve the problem:


\(O(\log n)\) Solution

Since the function \(2^a\) grows very quickly, we can consider enumerating values of \(a\) and calculate the valid range of \(b\) accordingly.

The original condition is:

\[ 1 \le 2^a \times b^2 \le n \]

If we fix a value of \(a\), we can move \(2^a\) to the right-hand side:

\[ 1 \le b^2 \le \frac{n}{2^a} \]

As \(b^2\) increases with \(b\), we can binary search to find the maximum valid \(b\).

However, this approach may count some values multiple times. Notice that when we compute for \(a = 2\), we already count all cases where \(a\) is divisible by \(2\), and when \(a = 1\), we cover all \(a\) where \(2 \nmid a\). So we only need to calculate for \(a = 1\) and \(a = 2\).

Thus, the overall time complexity is \(O(\log n)\), which is efficient enough for this problem.

#pragma GCC optimize(3,"Ofast","inline","unroll-loops")
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1000010;
int a[N];
signed main() {
    cin.tie(0)->sync_with_stdio(false);
    int n;cin>>n;int cnt=0;
    for(int i=1;i<=2;++i){
        int k=(1ll<<i);
        if(k>n)break;
        if(k==n)++cnt;
        else{
            int l=1,r=n,best=0;
            while(l<=r){
                int mid=l+r>>1;
                __int128 val=(__int128)k*mid*mid;
                if(val<=n)best=mid,l=mid+1;
                else r=mid-1;
            }
            cnt+=best;
        }
    }
    cout<<cnt<<'\n';
    return 0;
}

\(O(1)\) Solution

We can further optimize the step where we calculate:

How many integers \(b\) satisfy \(1 \le b^2 \le \frac{n}{2^a}\)?

Taking the square root on both sides gives:

\[ 1 \le b \le \sqrt{\frac{n}{2^a}} \]

So the number of valid \(b\) is:

\[ \left\lfloor \sqrt{\frac{n}{2^a}} \right\rfloor \]

This value can be computed in \(O(1)\) time using built-in functions like sqrtl in C++ or math.isqrt in Python.

#pragma GCC optimize(3,"Ofast","inline","unroll-loops")
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1000010;
int a[N];
signed main() {
    cin.tie(0)->sync_with_stdio(false);
    int n;cin>>n;
    int c1=sqrtl(n/2),c2=sqrtl(n/4);
    cout<<c1+c2<<'\n';
    return 0;
}
import math
n=int(input())
c1=int(math.isqrt(n//2))
c2=int(math.isqrt(n//4))
print(c1+c2)

posted:
last update: