The powerful array of a non-negative integer x is defined as the shortest sorted array of powers of two that sum up to x. The table below illustrates examples of how the powerful array is determined. It can be proven that the powerful array of x is unique.
num
Binary Representation
powerful array
1
0000 1
[1]
8
0 1 000
[8]
10
0 1 0 1 0
[2, 8]
13
0 11 0 1
[1, 4, 8]
23
1 0 111
[1, 2, 4, 16]
The array big_nums is created by concatenating the powerful arrays for every positive integer i in ascending order: 1, 2, 3, and so on. Thus,
big_nums begins as [_1_ , _2_ , _1, 2_ , _4_ , _1, 4_ , _2, 4_ , _1, 2, 4_ , _8_ , ...].
You are given a 2D integer matrix queries, where for queries[i] = [fromi, toi, modi] you should calculate (big_nums[fromi] * big_nums[fromi + 1] * ...* big_nums[toi]) % modi.
Return an integer array answer such that answer[i] is the answer to the ith query.
Input: queries =[[2,5,3],[7,7,4]]Output: [2,2]Explanation:
There are two queries.First query:`big_nums[2..5] = [1,2,4,1]`. The product of them is8. The
result is`8 % 3 = 2`.Second query:`big_nums[7] = 2`. The result is`2 % 4 = 2`.
The powerful array for each integer is the set of powers of two corresponding to the set bits in its binary representation. The concatenated array grows quickly, so we need to efficiently map a query index to the corresponding number and bit. We can precompute the lengths and use prefix products for fast queries.
classSolution {
public: vector<int> findProducts(vector<vector<int>>& queries) {
vector<int> lens = {0};
for (int i =1; lens.back() <1e6; ++i) {
lens.push_back(lens.back() + __builtin_popcount(i));
}
vector<int> ans;
for (auto& q : queries) {
int l = q[0], r = q[1], mod = q[2];
longlong res =1;
int li = lower_bound(lens.begin(), lens.end(), l) - lens.begin();
int ri = lower_bound(lens.begin(), lens.end(), r) - lens.begin();
int lp = l - lens[li-1], rp = r - lens[ri-1];
if (li == ri) {
vector<int> bits;
for (int b =0; b <32; ++b) if ((li >> b) &1) bits.push_back(1<< b);
for (int i = lp-1; i < rp; ++i) res = res * bits[i] % mod;
} else {
vector<int> bitsl, bitsr;
for (int b =0; b <32; ++b) {
if ((li >> b) &1) bitsl.push_back(1<< b);
if ((ri >> b) &1) bitsr.push_back(1<< b);
}
for (int i = lp-1; i < bitsl.size(); ++i) res = res * bitsl[i] % mod;
for (int num = li+1; num < ri; ++num) {
for (int b =0; b <32; ++b) if ((num >> b) &1) res = res * (1<< b) % mod;
}
for (int i =0; i < rp; ++i) res = res * bitsr[i] % mod;
}
ans.push_back(res);
}
return ans;
}
};
classSolution {
public List<Integer>findProducts(int[][] queries) {
List<Integer> lens =new ArrayList<>();
lens.add(0);
for (int i = 1; lens.get(lens.size()-1) < 1e6; i++) {
lens.add(lens.get(lens.size()-1) + Integer.bitCount(i));
}
List<Integer> ans =new ArrayList<>();
for (int[] q : queries) {
int l = q[0], r = q[1], mod = q[2];
long res = 1;
int li = Collections.binarySearch(lens, l);
if (li < 0) li =-li - 1;
int ri = Collections.binarySearch(lens, r);
if (ri < 0) ri =-ri - 1;
int lp = l - lens.get(li-1), rp = r - lens.get(ri-1);
if (li == ri) {
List<Integer> bits =new ArrayList<>();
for (int b = 0; b < 32; b++) if (((li >> b) & 1) == 1) bits.add(1 << b);
for (int i = lp-1; i < rp; i++) res = res * bits.get(i) % mod;
} else {
List<Integer> bitsl =new ArrayList<>(), bitsr =new ArrayList<>();
for (int b = 0; b < 32; b++) {
if (((li >> b) & 1) == 1) bitsl.add(1 << b);
if (((ri >> b) & 1) == 1) bitsr.add(1 << b);
}
for (int i = lp-1; i < bitsl.size(); i++) res = res * bitsl.get(i) % mod;
for (int num = li+1; num < ri; num++) {
for (int b = 0; b < 32; b++) if (((num >> b) & 1) == 1) res = res * (1 << b) % mod;
}
for (int i = 0; i < rp; i++) res = res * bitsr.get(i) % mod;
}
ans.add((int)res);
}
return ans;
}
}
classSolution {
funfindProducts(queries: Array<IntArray>): List<Int> {
val lens = mutableListOf(0)
while (lens.last() < 1e6) lens.add(lens.last() + Integer.bitCount(lens.size))
val ans = mutableListOf<Int>()
for (q in queries) {
val(l, r, mod) = q
var res = 1Lvar li = lens.binarySearch(l)
if (li < 0) li = -li - 1var ri = lens.binarySearch(r)
if (ri < 0) ri = -ri - 1val lp = l - lens[li-1]
val rp = r - lens[ri-1]
if (li == ri) {
val bits = (0..31).filter { (li shr it) and 1==1 }.map { 1 shl it }
for (i in lp-1 until rp) res = res * bits[i] % mod
} else {
val bitsl = (0..31).filter { (li shr it) and 1==1 }.map { 1 shl it }
val bitsr = (0..31).filter { (ri shr it) and 1==1 }.map { 1 shl it }
for (i in lp-1 until bitsl.size) res = res * bitsl[i] % mod
for (num in li+1 until ri) for (b in0..31) if ((num shr b) and 1==1) res = res * (1 shl b) % mod
for (i in0 until rp) res = res * bitsr[i] % mod
}
ans.add(res.toInt())
}
return ans
}
}
classSolution:
deffindProducts(self, queries: list[list[int]]) -> list[int]:
lens = [0]
i =1while lens[-1] <10**6:
lens.append(lens[-1] + bin(i).count('1'))
i +=1 ans = []
for l, r, mod in queries:
li = next(i for i in range(len(lens)) if lens[i] >= l)
ri = next(i for i in range(len(lens)) if lens[i] >= r)
lp = l - lens[li-1]
rp = r - lens[ri-1]
res =1if li == ri:
bits = [1<< b for b in range(32) if (li >> b) &1]
for i in range(lp-1, rp):
res = res * bits[i] % mod
else:
bitsl = [1<< b for b in range(32) if (li >> b) &1]
bitsr = [1<< b for b in range(32) if (ri >> b) &1]
for i in range(lp-1, len(bitsl)):
res = res * bitsl[i] % mod
for num in range(li+1, ri):
for b in range(32):
if (num >> b) &1:
res = res * (1<< b) % mod
for i in range(rp):
res = res * bitsr[i] % mod
ans.append(res)
return ans
impl Solution {
pubfnfind_products(queries: Vec<Vec<i32>>) -> Vec<i32> {
letmut lens =vec![0];
letmut i =1;
while*lens.last().unwrap() <1_000_000 {
lens.push(lens.last().unwrap() + i.count_ones() asi32);
i +=1;
}
letmut ans =vec![];
for q in queries.iter() {
let (l, r, m) = (q[0], q[1], q[2]);
let li = lens.iter().position(|&x| x >= l).unwrap();
let ri = lens.iter().position(|&x| x >= r).unwrap();
let lp = l - lens[li-1];
let rp = r - lens[ri-1];
letmut res =1i64;
if li == ri {
let bits: Vec<i64>= (0..32).filter(|&b| (li >> b) &1==1).map(|b|1<< b).collect();
for i in (lp-1)..rp {
res = res * bits[i asusize] % m asi64;
}
} else {
let bitsl: Vec<i64>= (0..32).filter(|&b| (li >> b) &1==1).map(|b|1<< b).collect();
let bitsr: Vec<i64>= (0..32).filter(|&b| (ri >> b) &1==1).map(|b|1<< b).collect();
for i in (lp-1)..(bitsl.len() asi32) {
res = res * bitsl[i asusize] % m asi64;
}
for num in (li+1)..ri {
for b in0..32 {
if (num >> b) &1==1 {
res = res * (1<< b) % m asi64;
}
}
}
for i in0..rp {
res = res * bitsr[i asusize] % m asi64;
}
}
ans.push(res asi32);
}
ans
}
}