Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- binary roots of an integer
- N is an integer within the range [1..2,147,483,647]. For example, given N = 3245 the function should return 55. Complexity:
- expected worst-case time complexity is O(sqrt(N));
- expected worst-case space complexity is O(1).
- #include <algorithm>
- #include <cassert>
- #include <cmath>
- #include <cstddef>
- #include <cstdlib>
- #include <iostream>
- #include <limits.h>
- template <typename UnsignedT>
- UnsignedT bit_rev(UnsignedT u)
- {
- UnsignedT ret = UnsignedT();
- std::size_t n;
- for (n = CHAR_BIT * (sizeof (UnsignedT)); n > 0 && !(u & (static_cast<UnsignedT>(0x1) << (n - 1))); --n)
- /* empty */;
- std::size_t i;
- for (i = 0; i < n; ++i) {
- ret |= ((u >> i) & 0x1) << (n - i - 1);
- }
- return ret;
- }
- long least_symmetric_binary_root(unsigned long N)
- {
- long ret = -1;
- unsigned long floor_sqrt_N = static_cast<unsigned long>(std::sqrt(static_cast<long double>(N)));
- while ((floor_sqrt_N + 1) * (floor_sqrt_N + 1) < N) {
- ++floor_sqrt_N;
- }
- unsigned long a;
- for (a = 1; a <= floor_sqrt_N; ++a) {
- if (N % a == 0) {
- unsigned long q = N / a;
- if (bit_rev(a) == q) { // `a` is a symmetric binary root of N.
- return a; // We know that it is the least symmetric binary root.
- // Proof:
- // Let (distinct and in ascending order) a_1, ..., a_n be all natural numbers such
- // that a_k <= sqrt(N) and a_k evenly divides N. Let q_k = N / a_k. For all k, q_k >= sqrt(N).
- // Suppose that N is such that at least one of { a_k } is a symmetric binary root (this case).
- // Let a_k be the first symmetric binary root of N (i.e. bit_rev(a_k) == q_k) among a_1, ..., a_n.
- // It could be that some of { q_1, ..., q_n } are symmetric binary roots, but for all j = 1 .. n, q_j >= sqrt(N) >= a_k.
- // Also, for j = k + 1 .. n, a_j > a_k. Therefore, a_k is the least symmetric binary root.
- } else if (bit_rev(q) == a) { // `q` is a symmetric binary root of N.
- ret = (ret == -1 ? q : std::min(ret, static_cast<long>(q)));
- }
- }
- }
- return ret;
- }
- int main()
- {
- assert(bit_rev(0x0U) == 0U);
- assert(bit_rev(0x80000000U) == 1U);
- assert(bit_rev(0x11U) == 17U);
- assert(bit_rev(0x7094FU) == 496775U);
- assert(bit_rev(0x2EFDB7U) == 3895261U);
- std::cout << least_symmetric_binary_root(50UL) << std::endl;
- assert(least_symmetric_binary_root(50UL) == 10L);
- std::cout << least_symmetric_binary_root(286UL) << std::endl;
- assert(least_symmetric_binary_root(286UL) == 22L);
- std::cout << least_symmetric_binary_root(256UL) << std::endl;
- assert(least_symmetric_binary_root(256UL) == 256L);
- return EXIT_SUCCESS;
- }
- #include <stdlib.h>
- #include <stdio.h>
- #include <math.h>
- // bit-reverse a number, the simple way
- static unsigned long bit_rev(unsigned long n){
- unsigned long r = 0;
- while(n){
- r = (r << 1) | (n&1);
- n >>= 1;
- }
- return r;
- }
- // find least symmetric binary root of an odd number
- static long int odd_sym_root(unsigned long n){
- unsigned long root_floor = (unsigned long)sqrt(n), r, q;
- // adjust the square root in case it's too small
- while(root_floor*(root_floor+2) < n) ++root_floor;
- // start at the smallest odd number with the same highest set
- // bit as the sqaure root
- r = root_floor;
- r |= r >> 1;
- r |= r >> 2;
- r |= r >> 4;
- r |= r >> 8;
- r |= r >> 16; // root_floor is < 2^32, so we can stop here
- r = ((r+1)/2)|1;
- while(r <= root_floor){
- q = n/r;
- // check if r divides n, the cofactor has the right number
- // of bits and finally if it's the bit-reversal of r
- if ((n == q*r) && (q < 2*r) && (q == bit_rev(r))){
- return r;
- }
- r += 2;
- }
- // n has no symmetric binary root
- return -1;
- }
- static long int least_symmetric_binary_root(unsigned long n){
- unsigned long m = n;
- unsigned k = 0;
- // find the odd part of n
- while((m&1) == 0){
- ++k;
- m >>= 1;
- }
- // find the least symmetric binary root of odd part
- long int r = odd_sym_root(m);
- // and shift if it has one
- return (r < 0) ? (-1) : (r << k);
- }
- int main(int argc, char *argv[]){
- unsigned long n = (argc > 1) ? strtoul(argv[1],NULL,0) : 25;
- long int r = least_symmetric_binary_root(n);
- if (r < 0){
- printf("No symmetric binary root.n");
- } else {
- printf("Least symmetric binary root: %ldn",r);
- }
- return EXIT_SUCCESS;
- }
Add Comment
Please, Sign In to add comment