I recently came across a problem where given a l and r you need to find out the sum of all x such that l <= x <= r (mod10^9 + 7).
And,
1 <= l <= r <= 10^18
Let sum(x) be the sum of fibonacci numbers upto x and let fibo(x) be the xth fibonacci number. It is known that
sum(x) = fibo(x+2) - 1
Using this I used this post to calculate the nth fibonacci term in O(logn) time.
I was wondering if it can be done any faster than this. Below is my implementation
public class FastFibonacci {
private static Map<BigInteger, BigInteger> map;
private static BigInteger mod = BigInteger.valueOf(1000000007);
public static BigInteger nthFibonacci(BigInteger num) {
if (num.compareTo(BigInteger.valueOf(2)) <= 0) return BigInteger.ONE;
return solve(num.subtract(BigInteger.ONE)).mod(BigInteger.valueOf(10000));
}
public static BigInteger solve(BigInteger num) {
if (map.get(num) != null) {
return map.get(num);
} else {
BigInteger k = num.divide(BigInteger.valueOf(2));
if (num.mod(BigInteger.valueOf(2)).compareTo(BigInteger.ZERO) == 0) {
// f(2*k)
map.put(num, (solve(k).multiply(solve(k)).mod(mod).add(solve(k.subtract(BigInteger.ONE)).multiply(solve(k.subtract(BigInteger.ONE))).mod(mod)).mod(mod)));
return map.get(num);
} else {
// f(2*k + 1)
map.put(num, (solve(k).multiply(solve(k.add( BigInteger.ONE))).mod(mod).add(solve(k).multiply(solve(k.subtract(BigInteger.ONE))).mod(mod))).mod(mod));
return map.get(num);
}
}
}
public static void main(String[] args) {
InputReader in = new InputReader(System.in);
map = new HashMap<>();
map.put(BigInteger.ZERO, BigInteger.ONE);
map.put(BigInteger.ONE, BigInteger.ONE);
int test = in.nextInt();
BigInteger[] ls = new BigInteger[test];
BigInteger[] rs = new BigInteger[test];
for (int i = 0; i < test; i++) {
ls[i] = new BigInteger(in.readString());
rs[i] = new BigInteger(in.readString());
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < test; i++) {
BigInteger sumUptoL = nthFibonacci(ls[i]).subtract(BigInteger.ONE);
BigInteger sumUptoR = nthFibonacci(rs[i].add(BigInteger.valueOf(1))).subtract(BigInteger.ONE);
sb.append(sumUptoR.subtract(sumUptoL));
sb.append("\n");
}
System.out.print(sb.toString());
}
}
Assuming that for a given number N you only want to know fib(N+2)-1 and you don't really need to show all the sequence, you can use a non-recursive approach. The following function uses double, but you can refactor it to BigInteger to accept bigger values:
public double getFibonacci(int n) {
double f1 = Math.pow(((1 + Math.sqrt(5)) / 2.0), n);
double f2 = Math.pow(((1 - Math.sqrt(5)) / 2.0), n);
return Math.floor((f1 - f2) / Math.sqrt(5));
}
Related
My task is to determine whether the sum of numbers in the Fibonacci series from A to B is divisible by the number D.
I use the fast doubling algorithm to find the required number in the series, and use the formula: Fa + ... + Fb = Fb+2 - 1 - (Fa+1 - 1) - to determine the sum of the series, but this is not enough. For testing, I took a series from A = 10,000,000 to B = 20,000,000, the number D = 987654, the program was executed in 3.3 seconds, this is a lot. Are there ways to optimize my code?
class Solution {
private static Map<BigDecimal, BigDecimal> previousValuesHolder;
static {
previousValuesHolder = new HashMap<>();
previousValuesHolder.put(BigDecimal.ZERO, BigDecimal.ZERO);
previousValuesHolder.put(BigDecimal.ONE, BigDecimal.ONE);
}
private static BigInteger totalSum;
public static void main(String args[]) {
Scanner in = new Scanner(System.in);
int nb = in.nextInt();
for (int i = 0; i < nb; i++) {
int a = in.nextInt();
int b = in.nextInt();
int d = in.nextInt();
totalSum = calculateTotalSum(a, b);
System.out.println(checkSum(totalSum, a, b, d));
}
}
private static BigInteger calculateTotalSum(int start, int finish) {
BigInteger res1 = fibDoubleFast(finish + 2).subtract(BigInteger.valueOf(1));
BigInteger res2 = fibDoubleFast(start + 1).subtract(BigInteger.valueOf(1));
return res1.subtract(res2);
}
private static String checkSum(BigInteger sum, int start, int finish, int d) {
BigInteger result = sum.remainder(BigInteger.valueOf(d));
return result.longValue() > 0
? String.format("F_%s + ... + F_%s is NOT divisible by %s", start, finish, d)
: String.format("F_%s + ... + F_%s is divisible by %s", start, finish, d);
}
private static BigInteger fibDoubleFast(int n) {
BigInteger a = BigInteger.ZERO;
BigInteger b = BigInteger.ONE;
int m = 0;
for (int bit = Integer.highestOneBit(n); bit != 0; bit >>>= 1) {
BigInteger d = multiply(a, b.shiftLeft(1).subtract(a));
BigInteger e = multiply(a, a).add(multiply(b, b));
a = d;
b = e;
m *= 2;
if ((n & bit) != 0) {
BigInteger c = a.add(b);
a = b;
b = c;
m++;
}
}
return a;
}
private static BigInteger multiply(BigInteger x, BigInteger y) {
return x.multiply(y);
}
}
For small values of D (less than 2^31, I think) , you could do the whole code using long, and do mod D for every intermediate result.
private static long fibDoubleFastModD(int n, long m) {
...
long d = (...) % m;
long e = (...) % m;
...
}
I am trying to calculate the fibonacci numbers within specific range(wide range of numbers in thousands)
I have wrote this but for I do not know to to modify it to make it within a range for example i need to get fibonacci numbers between 5027 and 8386589
class Fibonacci
{
public static void main(String args[])
{
int n1=0,n2=1,n3,i,count=10;
System.out.print(n1+" "+n2);//printing 0 and 1
for(i=2;i<count;++i)
{
n3=n1+n2;
System.out.print(" "+n3);
n1=n2;
n2=n3;
}
}
}
int fib(int low, int high){
// Initialize first three Fibonacci Numbers
int n1 = 0, n2 = 1, n3 = 1;
// Count fibonacci numbers in given range
int result = 0;
while (n1 <= high){
if (n1 >= low)
result++;
f1 = f2;
f2 = f3;
f3 = f1 + f2;
}
return result;
}
Try using a while loop instead of a for loop and include an if-statement
while(n3<8386589){
if(n3>5027){
System.out.print(n3+" ");
}
n3=n1+n2;
n1=n2;
n2=n3;
}
FWIW, here's my version (also using a while loop):
private static void Fibonacci(long lower, long upper)
{
long curr = 1, prev = 1;
while (curr <= upper)
{
long temp = curr;
curr = prev + curr;
prev = temp;
if (curr >= lower && curr <= upper)
{
System.out.println(curr);
}
}
}
The some idea just using BigInteger for bigger values :
private static BigInteger function_f(int n) {
// if n = 0 => f(n) = 0
if(n == 0)
return new BigInteger("0");
// Initialization of variables
// if n = 1 => f(n) = 1 (case included)
BigInteger result = new BigInteger("1");
BigInteger last_fn = new BigInteger("0");
BigInteger before_last_fn = new BigInteger("0");
// Do the loop for n > 1
for (int i = 2; i <= n; i++) {
// f(n - 2)
before_last_fn = last_fn;
// f(n - 1)
last_fn = result;
// f(n - 1) + f(n - 2)
result = last_fn.add(before_last_fn);
}
// Return the result
return result;
}
I need a help to complete a program that will generate a wordlist from chosen characters and length (it need to support a big length).
At first you need to fix this both by adding the length (wordlength) wanted and making a string of the specified characters(alphabet).
So the full number of words is:
long MAX_WORDS = (long) Math.pow(alphabet.length(), wordlength);
Actually, I made it and it work (for the example of short word of 2 or 66 characters).
import java.math.BigInteger;
public class wordlistgenenreg {
public static void main(String[] args) {
generate();
}
private static void generate(){
int wordlength =2;
String alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_~";
final long MAX_WORDS = (long) Math.pow(alphabet.length(), wordlength);
final int RADIX = alphabet.length();
for (long i = 0; i < MAX_WORDS; i++) {
int[] indices = convertToRadix(RADIX, i, wordlength);
char[] word = new char[wordlength];
for (int k = 0; k < wordlength; k++) {word[k] = alphabet.charAt(indices[k]);}
String fullword=new String(word);
System.out.println(fullword);
}
System.out.println("completed!");
}
private static int[] convertToRadix(int radix, long number, int wordlength) {
int[] indices = new int[wordlength];
for (int i = wordlength - 1; i >= 0; i--) {
if (number > 0) {
int rest = (int) (number % radix);
number /= radix;
indices[i] = rest;
} else {
indices[i] = 0;
}
}
return indices;
}
}
but there are a problem when i want to generate a really big string of 64 characters from 66. Because:
MAX_WORDS = 66^64 = 282365657377235405270307754780751252031361330095689004197961218014051357270480550051149871489969454245263206971867136
So I tried to change it to make it work with the BigInteger. But us a result, I always obtain the String:
"0000000000000000000000000000000000000000000000000000000000000000"
So there are a problem that i didn't figure it out. This my work on changing it:
import java.math.BigInteger;
public class wordlistgen {
public static void main(String[] args) {
generate();
}
private static void generate() {
int wordlength = 64;
String alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_~";
BigInteger max_words=new BigInteger("282365657377235405270307754780751252031361330095689004197961218014051357270480550051149871489969454245263206971867136");
final int RADIX = alphabet.length();
BigInteger plus=BigInteger.valueOf(1);
for (BigInteger i = new BigInteger("0"); i.compareTo(max_words) <0; i.add(plus)) {
int[] indices = convertToRadix(RADIX, i, wordlength);
char[] word = new char[wordlength];
for (int k = 0; k < wordlength; k++) {word[k] = alphabet.charAt(indices[k]);}
String fullword=new String(word);
System.out.println(fullword);
}
}
private static int[] convertToRadix(int radix, BigInteger i2, int wordlength) {
BigInteger zero=BigInteger.valueOf(0);
BigInteger big_radix=BigInteger.valueOf(radix);
int[] indices = new int[wordlength];
for (int i = wordlength - 1; i >= 0; i--) {
if (i2.compareTo(zero)==0) {
BigInteger rest =i2.remainder(big_radix);
BigInteger ab=i2.divide(big_radix);
i2=ab;
indices[i] = rest.intValue();
} else {
indices[i] = 0;
}
}
return indices;
}
}
This is the if from your original version:
if (number > 0) {
int rest = (int) (number % radix);
number /= radix;
indices[i] = rest;
} else {
indices[i] = 0;
}
And the same if in the BigInteger version:
if (i2.compareTo(zero)==0) {
BigInteger rest =i2.remainder(big_radix);
BigInteger ab=i2.divide(big_radix);
i2=ab;
indices[i] = rest.intValue();
} else {
indices[i] = 0;
}
As you can see, in your new if, you are asking if number == 0 instead of number > 0. So you always end up in the else.
As a side note: you are running a loop from 0 to your max_words. If each iteration takes merely a nanosecond to complete, it will still take 368788667672120349090672500612638816231217766896306723928560063188563281831044121479026746095987887263264265 years. Enough time for the universe to disintegrate into full entropy. I'd suggest re-thinking your algorithm.
Alright I am trying to solve a challenge one of my friends gave me to do, well I've manged to cut the last 9 digits out of a BigInteger well I had a way to cut-off the first 9 but it was so slow, it was taking too long.
The reason I need the first 9 and the last 9 is because I am looking for a BigInteger where the first and last are pandigital.
If you do not understand what I mean say we have n = new BigInteger("123456789987654321") well I need to get the "123456789" and the "987654321" seperately, and I do NOT want to convert the BigInteger to a string because that's a VERY slow process.
I am going for speed here, I am just stumped on this solution. I've heard something about using the Golden Ratio? Here is my code if you're interested.
import java.math.BigInteger;
public class Main {
public static void main(String...strings)
{
long timeStart = System.currentTimeMillis();
fib(350_000);
long timeEnd = System.currentTimeMillis();
System.out.println("Finished processing, time: " + (timeEnd - timeStart) + " milliseconds.");
}
public static BigInteger fib(int n)
{
BigInteger prev1 = BigInteger.valueOf(0), prev2 = BigInteger.valueOf(1);
for (int i = 0; i < n; i++)
{
// TODO: Check if the head is pandigital as well.
BigInteger tailing9Digits = tailing9Digits(prev1);
boolean tailPandigital = isPanDigital(tailing9Digits);
if (tailPandigital)
{
System.out.println("Solved at index: " + i);
break;
}
BigInteger savePrev1 = prev1;
prev1 = prev2;
prev2 = savePrev1.add(prev2);
}
return prev1;
}
public static BigInteger leading9Digits(BigInteger x)
{
// STUCK HERE.
return null;
}
public static BigInteger tailing9Digits(BigInteger x)
{
return x.remainder(BigInteger.TEN.pow(9));
}
static BigInteger[] pows = new BigInteger[16];
static
{
for (int i = 0; i < 16; i++)
{
pows[i] = BigInteger.TEN.pow(i);
}
}
static boolean isPanDigital(BigInteger n)
{
if (!n.remainder(BigInteger.valueOf(9)).equals(BigInteger.ZERO))
{
return false;
}
boolean[] foundDigits = new boolean[9];
boolean isPanDigital = true;
for (int i = 1; i <= 9; i++)
{
BigInteger digit = n.remainder(pows[i]).divide(pows[i - 1]);
for (int j = 0; j < foundDigits.length; j++) {
if (digit.equals(BigInteger.valueOf(j + 1)) && !foundDigits[j])
{
foundDigits[j] = true;
}
}
}
for (int i = 0; i < 9; i++)
{
isPanDigital = isPanDigital && foundDigits[i];
}
return isPanDigital;
}
}
BigInteger isn't something I'd recommend using if you care at all about speed. Most of its methods are poorly-implemented, and this typically results in very slow code.
There's a divide-and-conquer trick for division and radix conversion that you might find helpful.
First, BigInteger's multiply() is quadratic. You'll need to work around that, otherwise these divide-and-conquer tricks won't lead to any speedup. Multiplication via the fast Fourier transform is reasonably fast and good.
If you want to convert a BigInteger to base 10, break it in half (bitwise) and write it as a * 256^k + b. One thing you can do is convert a and b to base-10 recursively, then convert 256^k to decimal by repeated squaring, and then, in base 10, multiply a by 256^k and add b to the result. Also, since you're only interested in the first few digits, you might not even need to convert b if the first few digits of a * 256^k can't possibly be influenced by adding something as small as b.
A similar trick works for division.
You can do bit-shifting and extraction using the toByteArray() method.
Well I believe this is what you need:
import java.math.BigInteger;
public class PandigitalCheck {
public static void main(String[] args) {
BigInteger num = new BigInteger("12345678907438297438924239987654321");
long timeStart = System.currentTimeMillis();
System.out.println("Is Pandigital: " + isPandigital(num));
long timeEnd = System.currentTimeMillis();
System.out.println("Time Taken: " + (timeEnd - timeStart) + " ms");
}
private static boolean isPandigital(BigInteger num) {
if (getTrailing9Digits(num).compareTo(getLeading9Digits(num)) == 0) {
return true;
}
return false;
}
private static BigInteger getLeading9Digits(BigInteger num) {
int length = getBigIntLength(num);
BigInteger leading9 = BigInteger.ZERO;
for (int i = 0; i < 9; i++) {
BigInteger remainder = num.divide(BigInteger.TEN.pow(length - 1 - i));
leading9 = leading9.add(remainder.multiply(BigInteger.TEN.pow(i)));
num = num.remainder(BigInteger.TEN.pow(length - 1 - i));
}
return leading9;
}
private static int getBigIntLength(BigInteger num) {
for (int i = 1; ; i++) {
if (num.divide(BigInteger.TEN.pow(i)) == BigInteger.ZERO) {
return i;
}
}
}
private static BigInteger getTrailing9Digits(BigInteger num) {
return num.remainder(BigInteger.TEN.pow(9));
}
}
The output is:
Is Pandigital: true
Time Taken: 0 ms
Does it fit the bill?
I’m newbie for java, I’m converting BigInteger to String only but it's little bit fast as your code
import java.math.BigInteger;
public class Main {
public static void main(String args[])
{
long timeStart = System.currentTimeMillis();
String biStr = new BigInteger("123456789987654321").toString();
int length=(biStr.length())/2;
String[] ints = new String[length];
String[] ints2 = new String[length];
for(int i=0; i<length; i++) {
int j=i+length;
ints[i] = String.valueOf(biStr.charAt(i));
ints2[i] = String.valueOf(biStr.charAt(j));
System.out.println(ints[i] +" | "+ints2[i]);
}
long timeEnd = System.currentTimeMillis();
System.out.println("Finished processing, time: " + (timeEnd - timeStart) + " milliseconds.");
}
}
Maybe this is not too fast but at least it's simple
BigInteger n = new BigInteger("123456789987654321");
BigInteger n2 = n.divide(BigInteger.TEN.pow(new BigDecimal(n).precision() - 9));
BigInteger n1 = n.remainder(new BigInteger("1000000000"));
System.out.println(n1);
System.out.println(n2);
output
987654321
123456789
I tried to find the factorial of a large number e.g. 8785856 in a typical way using for-loop and double data type.
But it is displaying infinity as the result, may be because it is exceeding its limit.
So please guide me the way to find the factorial of a very large number.
My code:
class abc
{
public static void main (String[]args)
{
double fact=1;
for(int i=1;i<=8785856;i++)
{
fact=fact*i;
}
System.out.println(fact);
}
}
Output:-
Infinity
I am new to Java but have learned some concepts of IO-handling and all.
public static void main(String[] args) {
BigInteger fact = BigInteger.valueOf(1);
for (int i = 1; i <= 8785856; i++)
fact = fact.multiply(BigInteger.valueOf(i));
System.out.println(fact);
}
You might want to reconsider calculating this huge value. Wolfram Alpha's Approximation suggests it will most certainly not fit in your main memory to be displayed.
This code should work fine :-
public class BigMath {
public static String factorial(int n) {
return factorial(n, 300);
}
private static String factorial(int n, int maxSize) {
int res[] = new int[maxSize];
res[0] = 1; // Initialize result
int res_size = 1;
// Apply simple factorial formula n! = 1 * 2 * 3 * 4... * n
for (int x = 2; x <= n; x++) {
res_size = multiply(x, res, res_size);
}
StringBuffer buff = new StringBuffer();
for (int i = res_size - 1; i >= 0; i--) {
buff.append(res[i]);
}
return buff.toString();
}
/**
* This function multiplies x with the number represented by res[]. res_size
* is size of res[] or number of digits in the number represented by res[].
* This function uses simple school mathematics for multiplication.
*
* This function may value of res_size and returns the new value of res_size.
*/
private static int multiply(int x, int res[], int res_size) {
int carry = 0; // Initialize carry.
// One by one multiply n with individual digits of res[].
for (int i = 0; i < res_size; i++) {
int prod = res[i] * x + carry;
res[i] = prod % 10; // Store last digit of 'prod' in res[]
carry = prod / 10; // Put rest in carry
}
// Put carry in res and increase result size.
while (carry != 0) {
res[res_size] = carry % 10;
carry = carry / 10;
res_size++;
}
return res_size;
}
/** Driver method. */
public static void main(String[] args) {
int n = 100;
System.out.printf("Factorial %d = %s%n", n, factorial(n));
}
}
Hint: Use the BigInteger class, and be prepared to give the JVM a lot of memory. The value of 8785856! is a really big number.
Use the class BigInteger. ( I am not sure if that will even work for such huge integers )
Infinity is a special reserved value in the Double class used when you have exceed the maximum number the a double can hold.
If you want your code to work, use the BigDecimal class, but given the input number, don't expect your program to finish execution any time soon.
The above solutions for your problem (8785856!) using BigInteger would take literally hours of CPU time if not days. Do you need the exact result or would an approximation suffice?
There is a mathematical approach called "Sterling's Approximation
" which can be computed simply and fast, and the following is Gosper's improvement:
import java.util.*;
import java.math.*;
class main
{
public static void main(String args[])
{
Scanner sc= new Scanner(System.in);
int i;
int n=sc.nextInt();
BigInteger fact = BigInteger.valueOf(1);
for ( i = 1; i <= n; i++)
{
fact = fact.multiply(BigInteger.valueOf(i));
}
System.out.println(fact);
}
}
Try this:
import java.math.BigInteger;
public class LargeFactorial
{
public static void main(String[] args)
{
int n = 50;
}
public static BigInteger factorial(int n)
{
BigInteger result = BigInteger.ONE;
for (int i = 1; i <= n; i++)
result = result.multiply(new BigInteger(i + ""));
return result;
}
}
Scanner r = new Scanner(System.in);
System.out.print("Input Number : ");
int num = r.nextInt();
int ans = 1;
if (num <= 0) {
ans = 0;
}
while (num > 0) {
System.out.println(num + " x ");
ans *= num--;
}
System.out.println("\b\b=" + ans);
public static void main (String[] args) throws java.lang.Exception
{
BigInteger fact= BigInteger.ONE;
int factorialNo = 8785856 ;
for (int i = 2; i <= factorialNo; i++) {
fact = fact.multiply(new BigInteger(String.valueOf(i)));
}
System.out.println("Factorial of the given number is = " + fact);
}
import java.util.Scanner;
public class factorial {
public static void main(String[] args) {
System.out.println("Enter the number : ");
Scanner s=new Scanner(System.in);
int n=s.nextInt();
factorial f=new factorial();
int result=f.fact(n);
System.out.println("factorial of "+n+" is "+result);
}
int fact(int a)
{
if(a==1)
return 1;
else
return a*fact(a-1);
}
}