Project Euler 97 - java

I'm trying to solve the Project Euler #97 problem. I don't want to look on the web because they give directly the solution.
Here's the exercise :
The first known prime found to exceed one million digits was
discovered in 1999, and is a Mersenne prime of the form 2^6972593−1;
it contains exactly 2,098,960 digits. Subsequently other Mersenne
primes, of the form 2^p−1, have been found which contain more digits.
However, in 2004 there was found a massive non-Mersenne prime which
contains 2,357,207 digits: 28433×2^7830457+1.
Find the last ten digits of this prime number.
So, I tried this :
public static void main(String []args){
BigInteger i = new BigInteger("28433")
.multiply(new BigInteger(String.valueOf(Math.pow(2, 7830457)))
.add(new BigInteger("1")));
String s = i.toString();
System.out.println(s.substring(s.length()-10, s.length()));
}
Obviously that does not work :
Exception in thread "main" java.lang.NumberFormatException: For input string: "Infinity"
How should I approach this problem (I'm really stuck) ? (please don't give the solution, just hints)
Thanks

You have a problem where you want the answer mod 10^10 (the last ten digits)
You can calculate powers faster by using powers of two. e.g. x*x = x^2, and x^2 * x^2 = x^4 and so on. 7 830 457 = 0b11101110111101110111001 is 2^23 + 2^22 + 2^21 + 2^19 ... 2^0 so it is x^(2^23) * x^(2^22) * x(2^21) * x ^(2^19) * ... x You have to perform each operation mod 10^10 to avoid overflow. You can the multiply this by the first constant and add 1.
Using this approach you can calculate in O(log N) where N is the power.
The key function which will do most of the work for you is BigInteger.modPow It is designed to calculate large powers efficiently but only calculating the lowest portion of a number (based on the mod chosen)

The problem is in calculating 2^7830457
they want the last 10 digits so that means the number mod 10000000000
according to this: http://en.wikipedia.org/wiki/Modulo_operation
ab mod n = ((a mod n)*(b mod n))mod n
so you can calculate 2^7830457 using multiplication in a loop where you take modulus after each multiplication
edit : recursive multiplication would be faster
public static long pow1(int a,long b,long n){
if (b==1)return a%n;
if (b%2==1){
return (pow1(a,(b-1)/2,n)*a)%n;
}
else{
return (pow1(a,b/2,n))%n;
}
}

there is a factor missing in the recursive code
def pow1(a,b,n):
if (b==1):
return a%n
if (b%2==1):
return (pow1(a,(b-1)//2,n)*pow1(a,b//2,n)*a)%n
else:
return (pow1(a,b//2,n)*pow1(a,b//2,n))%n

My method was to calculate 2^7830457 mod 10000000000 using successive squaring algoritm, multiplying the result by 28433 and adding one. Well within excel's capability.

Related

Concatenation of Consecutive Binary Numbers, Modulo Operation discussion behavior

Here I am contributing the Java Solution for the problem.
Concatenation of Consecutive Binary Numbers:
Given an integer n, return the decimal value of the binary string formed by concatenating the binary representations of 1 to n in order, modulo 10^9 + 7.
class Solution {
public int concatenatedBinary(int n) {
long sum = 0;
for(int i = 1; i <= n; i++){
sum = ((sum << Integer.toBinaryString(i).length()) + i) % 1000000007;
}
return (int) sum;
}
}
Now I have a doubt that is when we are modulating at each step within for loop. It will not impact the result till 1000000007 but after that, it will change the sum variable, and this cycle will repeat. Now, why doesn't this modulo impacting the overall result? Thanks in advance.
Let's take a simpler problem: Take the number 1000, write it as bits, then take the number 1001, write that as bits, concatenate the two, what's that, in decimal?
1000 in bits is 11 1110 1000
1001 in bits is 11 1110 1001
Thus, the answer'd be 1111 1010 0011 1110 1001, or 1025001.
But, let's do a more mathy take on this: "concatenate the two" boils down to: "Shift the bits in the first number to the left to make enough room, then add the second number". And "shift left by X" is the same as 'multiply by 2X'. Just like if I have the number '1234', and I tell you to 'shift that left by 2 spots', it's the same as multiplying by 100: That turns it into 123400, which is 1234*100, and 100 is just 102. So, 'shift left by X spots' is the same as 'multiply by bX' where b is the 'base' of the number system we use; 2 in binary, 10 in decimal.
Thus, a different way to state the same result is: 'Take the number 1000, multiply it by 210, add 1001 to it. Sure enough: 1000 * 2^10 + 1001 is indeed 1025001.
Thus, a single 'loop' in your algorithm is effectively: Take the result we have so far, multiply it by 2 a bunch of times (X times, where X is the position of the highest 1-bit in the number we're processing this loop), then add the new number.
So, it's just multiplication and addition.
Modulo has the property that it is stable for those operations.
Consider basic math: You were probably taught about the number line. A horizontal line, infinite in size.
A modulo system is no different, except the number line is a big loop. It's a circle. In modulo 1000000007 space, the numbers '5 and 6' are just as adjacent as the numbers '0 and 1000000006' are.
Given, on the normal number line, a * b = c, modulo has the property that this also means that (a%Z * b%Z)%Z = c%Z for any Z. The same goes for addition; if a + b = c, then (a%Z + b%Z)%Z = c%Z is also true. You can try a bunch of numbers and witness this, or try to prove this yourself, or search the web for proof of this property.
Example:
12 * 18 = 216
(12%7 * 18%7)%7 = 216%7
Yup, that checks out:
5 * 4 = 20
20%7 = 6.
216%7 is also 6.
Thus:
Your question boils down to a lot of applications of multiplying and addition.
multiply and add translate to modulo math without issue.
Therefore, your algorithm works.

Sum a series n^n for values 1 through n with no overflow? Only last digits of answer needed

I want to write a Java program that sums all the integers n^n from 1 through n. I only need the last 10 digits of this number, but the values given for n exceed 800.
I have already written a basic java program to calculate this, and it works fine for n < 16. But it obviously doesn't deal with such large numbers. I am wondering if there is a way to just gather the last 10 digits of a number that would normally overflow a long, and if so, what that method or technique might be.
I have no code to show, just because the code I wrote already is exactly what you'd expect. A for loop that runs i*i while i<=n and a counter that sums each iteration with the one before. It works. I just don't know how to approach the problem for bigger numbers, and need guidance.
Around n=16, the number overflows a long, and returns negative values. Will BigInteger help with this, or is that still too small a data type? Or could someone point me towards a technique for gathering the last 10 digits of a massive number? I could store it in an array and then sum them up if I could just get that far.
Anyhow, I don't expect a finished piece of code, but maybe some suggestions as to how I could look at this problem anew? Some techniques my n00b self is missing?
Thank you!
sums all the integers n^n from 1 through n. I only need the last 10 digits of this number
If you only need last 10 digits, that means you need sum % 10¹⁰.
The sum is 1¹ + 2² + 3³ + ... nⁿ.
According to equivalences rules:
(a + b) % n = [(a % n) + (b % n)] % n
So you need to calculate iⁱ % 10¹⁰, for i=1 to n, sum them, and perform a last modulus on that sum.
According to the modular exponentiation article on Wikipedia, there are efficient ways to calculate aⁱ % m on a computer. You should read the article.
However, as the article also says:
Java's java.math.BigInteger class has a modPow() method to perform modular exponentiation
Combining all that to an efficient implementation in Java that doesn't use excessive amounts of memory:
static BigInteger calc(int n) {
final BigInteger m = BigInteger.valueOf(10_000_000_000L);
BigInteger sum = BigInteger.ZERO;
for (int i = 1; i <= n; i++) {
BigInteger bi = BigInteger.valueOf(i);
sum = sum.add(bi.modPow(bi, m));
}
return sum.mod(m);
}
Or the same using streams:
static BigInteger calc(int n) {
final BigInteger m = BigInteger.valueOf(10).pow(10);
return IntStream.rangeClosed(1, n).mapToObj(BigInteger::valueOf).map(i -> i.modPow(i, m))
.reduce(BigInteger.ZERO, BigInteger::add).mod(m);
}
Test
System.out.println(calc(800)); // prints: 2831493860
BigInteger would be suitable to work with these kinds of numbers. It's quite frankly what it's designed for.
Do note that instances of BigInteger are immutable and any operations you do on one will give you back a new BigInteger instance. You're going to want to store some of your results in variables.

calculate kth power of 2

I was solving a problem and the basic idea to calculate the power of 2 for some k. And then multiply it with 10. Result should be calculated value mod
10^9+7.
Given Constraints 1≤K≤10^9
I am using java language for this. I used 'Math.pow' function but 2^10000000 exceeds its range and I don't want to use 'BigInteger' here. Any other way to calculate such large values.
The actual problem is:
For each valid i, the sign with number i had the integer i written on one side and 10K−i−1 written on the other side.
Now, Marichka is wondering — how many road signs have exactly two distinct decimal digits written on them (on both sides in total)? Since this number may be large, compute it modulo 10^9+7.
I'm using this pow approach, but this is not an efficient way. Any suggestion to solve this problem.
My original Solution:
/* package codechef; // don't place package name! */
import java.util.*;
class Codechef
{
public static void main (String[] args) throws java.lang.Exception
{
Scanner scan = new Scanner(System.in);
int t = scan.nextInt();
while(t-->0){
long k = scan.nextInt();
long mul=10*(long)Math.pow(2, k-1);
long ans = mul%1000000007;
System.out.println(ans);
}
}
}
After taking some example, I reached that this pow solution works fine for small constraints but not for large.
while(t-->0){
long k = scan.nextInt();
long mul=10*(long)Math.pow(2, k);
long ans = mul%1000000007;
System.out.println(ans);
}
This pow function is exceeding its range. Any good solution to this.
Basically, f(g(x)) mod M is the same as f(g(x) mod M) mod M. As exponentiation is just a lot of multiplication, you can just decompose your single exponentiation into many multiplications, and apply modulo at every step. i.e.
10 * 2^5 mod 13
is the same as
10
* 2 mod 13
* 2 mod 13
* 2 mod 13
* 2 mod 13
* 2 mod 13
You can compact the loop by not breaking up the exponentiation so far; i.e. this would give the same answer, again:
10
* 4 mod 13
* 4 mod 13
* 2 mod 13
Faruk's recursive solution shows an elegant way to do this.
You need to use the idea of dividing the power by 2.
long bigmod(long p,long e,long M) {
if(e==0)
return 1;
if(e%2==0) {
long t=bigmod(p,e/2,M);
return (t*t)%M;
}
return (bigmod(p,e-1,M)*p)%M;
}
while(t-->0){
long k = scan.nextInt();
long ans = bigmod(2, k, 1000000007);
System.out.println(ans);
}
You can get details about the idea from here: https://www.geeksforgeeks.org/how-to-avoid-overflow-in-modular-multiplication/
As the size of long is 8 bytes and it is signed datatype so the range of long datatype is -(2^63) to (2^63 - 1). Hence to store 2^100 you have to use another datatype.

Summation equation in Java?

I would like to know how I would go about writing this summation equation in java. But, the trick is, I need the summation to be equal to an amount.
x= Total Loss Streak amount
sb= Starting Bet
m= multiplier
The whole equation will equal to the current amount of currency in one's account. The amount of times the summation can complete itself while adding up needs to be less than or equal to the amount of currency in ones account.
Fyi, this is for a dicebot that work's on peerbet.org and I want to be able to show the user how many times he can loose in a row without wasting all his money.
If this question is bad, please do not answer it and let me delete it. Also, it thought the middle part was code, so I had to put it as such or it wouldn't let me post.
Renaming sb to just b. This is just a sum of a geometric progression
In Java, you can write:
return b * (m * m - Math.pow(m, x + 1)) / (1 - m);
This will be considerably faster than using a loop, although you must check that m is not 1.
If you want to solve for x given a sum S then a rearrangement of the formula gives the following Java code:
double x = Math.log(m * m - S * (1 - m) / b) / log(m) - 1;
and truncate this result to get the integral value of x where the next integer bankrupts the player.
EDIT: apparently we are solving for x. still easily doable with a loop.
int sum = 0;
int x =2;
while(sum<=amount){
sum+=sb*(Math.pow(m,x));
}
return x;
A summation is really just an adding for loop right?
int sum = 0;
for(int i=2; i<x; i++){
sum+=sb*(Math.pow(m,i));
}
return sum;
I'm not entirely clear I'm reading your formula correctly: are you summing up integers from 2 to x on the left-hand side of the equals sign, and you want that sum to be equal to the term on the right-hand side?
In that case, we could do the following transformation:
(Note that the first step might not be what you had in mind.)
We can now easily solve this using the quadratic formula to get:
Assuming that we're calculating in the reals, note that the root is only defined for non-negative arguments. The result of taking that root yields a non-negative number and substracting that non-negative number from -1 would give something <= -1, i.e., a negative number. Dividing it by 2 won't make it positive, either, but we've assumed from the get-go that our x must be >= 2, or else the very first sum wouldn't make any sense.
Therefore we can disregard the - case of the +/- in the formula altogether. Hence:
This should be straight-forward to translate into Java code, but note that the result is likely not to be an integer, so you will have to round if you're looking for an upper bound.

Issue with implementation of Fermat's little therorm

Here's my implementation of Fermat's little theorem. Does anyone know why it's not working?
Here are the rules I'm following:
Let n be the number to test for primality.
Pick any integer a between 2 and n-1.
compute a^n mod n.
check whether a^n = a mod n.
myCode:
int low = 2;
int high = n -1;
Random rand = new Random();
//Pick any integer a between 2 and n-1.
Double a = (double) (rand.nextInt(high-low) + low);
//compute:a^n = a mod n
Double val = Math.pow(a,n) % n;
//check whether a^n = a mod n
if(a.equals(val)){
return "True";
}else{
return "False";
}
This is a list of primes less than 100000. Whenever I input in any of these numbers, instead of getting 'true', I get 'false'.
The First 100,008 Primes
This is the reason why I believe the code isn't working.
In java, a double only has a limited precision of about 15 to 17 digits. This means that while you can compute the value of Math.pow(a,n), for very large numbers, you have no guarantee you'll get an exact result once the value has more than 15 digits.
With large values of a or n, your computation will exceed that limit. For example
Math.pow(3, 67) will have a value of 9.270946314789783e31 which means that any digit after the last 3 is lost. For this reason, after applying the modulo operation, you have no guarantee to get the right result (example).
This means that your code does not actually test what you think it does. This is inherent to the way floating point numbers work and you must change the way you hold your values to solve this problem. You could use long but then you would have problems with overflows (a long cannot hold a value greater than 2^64 - 1 so again, in the case of 3^67 you'd have another problem.
One solution is to use a class designed to hold arbitrary large numbers such as BigInteger which is part of the Java SE API.
As the others have noted, taking the power will quickly overflow. For example, if you are picking a number n to test for primality as small as say, 30, and the random number a is 20, 20^30 = about 10^39 which is something >> 2^90. (I took the ln of 10^39).
You want to use BigInteger, which even has the exact method you want:
public BigInteger modPow(BigInteger exponent, BigInteger m)
"Returns a BigInteger whose value is (this^exponent mod m)"
Also, I don't think that testing a single random number between 2 and n-1 will "prove" anything. You have to loop through all the integers between 2 and n-1.
#evthim Even if you have used the modPow function of the BigInteger class, you cannot get all the prime numbers in the range you selected correctly. To clarify the issue further, you will get all the prime numbers in the range, but some numbers you have are not prime. If you rearrange this code using the BigInteger class. When you try all 64-bit numbers, some non-prime numbers will also write. These numbers are as follows;
341, 561, 645, 1105, 1387, 1729, 1905, 2047, 2465, 2701, 2821, 3277, 4033, 4369, 4371, 4681, 5461, 6601, 7957, 8321, 8481, 8911, 10261, 10585, 11305, 12801, 13741, 13747, 13981, 14491, 15709, 15841, 16705, 18705, 18721, 19951, 23001, 23377, 25761, 29341, ...
https://oeis.org/a001567
161038, 215326, 2568226, 3020626, 7866046, 9115426, 49699666, 143742226, 161292286, 196116194, 209665666, 213388066, 293974066, 336408382, 376366, 666, 566, 566, 666 2001038066, 2138882626, 2952654706, 3220041826, ...
https://oeis.org/a006935
As a solution, make sure that the number you tested is not in this list by getting a list of these numbers from the link below.
http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html
The solution for C # is as follows.
public static bool IsPrime(ulong number)
{
return number == 2
? true
: (BigInterger.ModPow(2, number, number) == 2
? (number & 1 != 0 && BinarySearchInA001567(number) == false)
: false)
}
public static bool BinarySearchInA001567(ulong number)
{
// Is number in list?
// todo: Binary Search in A001567 (https://oeis.org/A001567) below 2 ^ 64
// Only 2.35 Gigabytes as a text file http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html
}

Categories