6

So, I am new to programming in c++ and i came across this question where i need to calculate pow(2,n)/2 where n>64 ?

i tried using unsigned long long int but as the limit of the c++ is only 2^64. So is there any method to calculate this.

Edit:

 1 < n < 10^5

The result of the expression is used in further calculation

The question is asked on online platform.So, i cant use libraries like gmp to handle large numbers.

Question

You are given with an array A of size N. An element Ai is said to be charged if its value (Ai) is greater than or equal to Ki. Ki is the total number of subsets of array A that consist of element Ai.
Total charge value of the array is defined as summation of all charged elements present in the array mod (10^9)+7.
Your task is to output the total charge value of the given array.

  • How big can n be? – melpomene Aug 02 '19 at 17:45
  • 1
    What do you want to do with the result, print it? I'm pretty sure a simple `std::cout << std::setprecision(1000) << std::pow(2.l,n) << '\n';` should work. – HolyBlackCat Aug 02 '19 at 17:49
  • 5
    If you want exact arithmetic, you should use a bignum library like gmp. – stark Aug 02 '19 at 17:51
  • n varies upto 100000 i.e (10^5) – Shiva Chandel Aug 02 '19 at 17:51
  • 1
    @HolyBlackCat: Implementations vary, but I'm not sure even modern implementations can get a thousand digits correct. 15 digits is easy, 30 is a bit of work. – MSalters Aug 02 '19 at 17:53
  • 1
    The GNU Multiple Precision Arithmetic Library https://gmplib.org, however consider what you want this for. If you are doing hard core number theory, go for it. If you are using this integer to do other computations, rethink your solution. – alfC Aug 02 '19 at 17:53
  • if you can afford loosing precision you can use `long double` – Guillaume Racicot Aug 02 '19 at 17:53
  • 1
    You might need to implement your own ultra-wide-exponent floating point type to represent that. What on earth are you going to _use_ your `2^100000` for after you've computed it? – hmakholm left over Monica Aug 02 '19 at 17:53
  • @GuillaumeRacicot: Even long double doesn't usually have room for exponents of more than 15 bits. – hmakholm left over Monica Aug 02 '19 at 17:55
  • 4
    Surely there's more to this problem? For example, maybe the question asks for `pow(2, n) mod p` or something like that? – harold Aug 02 '19 at 17:58
  • 2
    This sounds like an [XY problem](https://meta.stackexchange.com/q/66377). If the question only asks you to print the result, you might be expected to implement your own big integer library or something similar. Since you mentioned that you need to use the results in further calculations, it is likely possible to manipulate your formulas to avoid computations with large numbers like this. So please post the full problem. – eesiraed Aug 02 '19 at 18:06
  • 2
    This doesn't address the question, but `pow(2,n)/2` is `pow(2,n-1)`. – Pete Becker Aug 02 '19 at 18:07
  • if you can answer in binary the answer is easy : 0b1 << n-1, so you generate a string with n-1 zeros and a 1 in front – willll Aug 02 '19 at 18:07
  • I'd just cheat and [not use C++](https://tio.run/##y0gszk7Nyfn/PzcxM0/BVqGgKDOvREHDSCFOwRIINP//BwA). – melpomene Aug 02 '19 at 18:12
  • @harold: Seems you guessed right. Yet another "do you know the rules of modular arithmetic?" questions, in particular `(a*b) mod p == (a mod p * b mod p) mod p`. – MSalters Aug 02 '19 at 19:01
  • The question does not ask you to calculate powers of 2. Since you ran into a technical limitation, I would guess the question's intent is for you to figure out how to get that result without needing to calculate numbers larger than 2^64. – JaMiT Aug 02 '19 at 19:43
  • Is that an exact copy of the question? I ask because with the way it is written, _**Ki**_ is either 0 or 1, as there is exactly one set consisting of element **_Ai_**. So the value of _**Ki**_ depends only on whether or not that set is a subset of array **A**. (There are more sets that *contain* "element **_Ai_**", but only one that *consists* of it.) Presumably that set will be a subset, but the question neglects to specify what **_Ai_** is. – JaMiT Aug 02 '19 at 19:50

2 Answers2

10

An important detail here is that you're not being asked to compute 2n for gigantic n. Instead, you're being asked to compute 2n mod 109 + 7 for large n, and that's a different question.

For example, let's suppose you want to compute 270 mod 109 + 1. Notice that 270 doesn't fit into a 64-bit machine word. However, 270 = 230 · 235, and 235 does fit into a 64-bit machine word. Therefore, we could do this calculation to get 270 mod 109 + 7:

270 (mod 109 + 7)

= 235 · 235 (mod 109 + 7)

= (235 mod 109 + 7) · (235 mod 109 + 7) mod 109 + 7

= (34359738368 mod 109 + 7) · (34359738368 mod 109 + 7) mod 109 + 7

= (359738130 · 359738130) mod 109 + 7

= 129411522175896900 mod 109 + 7

= 270016253

More generally, by using repeated squaring, you can compute 2n mod 109 + 7 for any value of n in a way that nicely fits into a 64-bit integer.

Hope this helps!

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
5

The common approach in serious numerical work is to rewrite the formula's. You store log(x) instead of x, and later when you do need x it will typically be in a context where you didn't need all those digits anyway.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • 1
    While I completely agree with you that in serious numerical work expressing things via logarithms is a great idea, this seems like it's in the context of a programming contest problem where exact values are needed. My suspicion is that they're looking for exponentiation by squaring with repeated mods. – templatetypedef Aug 02 '19 at 18:50