Improving brute force solution to Project euler #25 - c++

I recently stumbled on this Project Euler Problem #25:
The 12th term, F12, is the first term to contain three digits.
What is the first term in the Fibonacci sequence to contain 1000 digits?
I just know C++98 and no other programming language. I have tried to solve it, making changes to get support of c++11.
Working:
#include <iostream>
#include<cstdio>
long len(long); //finding length
int main()
{
/* Ques: What is the first term in fibonacci series to contain 1000 digits? */
int ctr=2;
unsigned long first, second, third, n;
first=1;
second=1;
std::cout<<"\t **Project EULER Question 25**\n\n";
for(int i=2;;++i)
{
third=first+second;
// cout<<" "<<third;
int x=len(third);
// cout<<" Length: "<<x;
// cout<<"\n";
first=second;
second=third;
ctr++;
if(x>1000) // for small values, program works properly
{
std::cout<< " THE ANSWER: "<< ctr;
system("pause");
break;
}
}
}
long len(long num)
{
int ctr=1;
while(num!=0)
{
num=num/10;
if(num!=0)
{
ctr++;
}
}
return(ctr);
}
I know this is brute force, but can i make it more efficient so that i get the answer ?
Any help will be greatly appreciated.
EDIT:
By using Binet's Formula, as suggested by PaulMcKenzie and implementing it as:
#define phi (1+sqrt(5))/2
int main(void)
{
float n= ((999 + (1/2)*log10(5))/(log10(phi))); //Line 1
cout<<"Number is : "<<n;
return 0;
}
Output: 4780.187012
Changing Line 1, above, to :
float n= ((999 + log10(sqrt(5)))/(log10(phi)));
OUTPUT: 4781.859375
What could be possibly the error here?

unsigned long simply can't hold 1000-digit number. So you will get the overflow in your code when first and second will reach the unsigned long limit. If you want a brute force solution - consider use of something like biginteger library or write one by yourself.

Related

AtCoder DP Contest Q -I Coins (getting wrong answer may be using double)

Link to Problem -> https://atcoder.jp/contests/dp/tasks/dp_i
question Coins-I
Code I wrote gave wrong answer to TEST CASE 3
5
0.42 0.01 0.42 0.99 0.42
Expected output
0.3821815872
MY code output
0.382182
As the error is greater than 1e-9 it got WA
What I tried:
I made double to long double but still it doesn't give accuracy
is there any way to increase the accuracy when working with double in this question.
#include<bits/stdc++.h>
using namespace std;
long double p[3000];
long double dp[3001][1501];
long double solve(int i,int tail_count){
if(dp[i][tail_count]!=2){
return dp[i][tail_count];
}
long double ans=0;
if(i==1 && tail_count==0)return p[1];
else if(i==1 && tail_count>0)return (long double)1;
else if(tail_count==0)ans= p[i]*solve(i-1,tail_count);
else ans= (p[i]*solve(i-1,tail_count)+(1-p[i])*solve(i-1,tail_count-1));
dp[i][tail_count]=ans;
return ans;
}
int main(){
for(int i=0;i<3000;i++){
for(int j=0;j<1500;j++){
dp[i][j]=2;
}
}
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>p[i];
}
cout<<solve(n,(n-1)/2);
return 0;
}
The number of digits to be printed via output streams is controlled by their precision parameter. The default is 6 digits, if you want more you need to adjust it accordingly by std::setprecision :
std::cout << std::setprecision(num_digits) << solve(n,(n-1)/2);
Most of your indexing is off by one. Valid indices of an array with N elements are 0 till (including) N-1. dp is 3001 x 1501 but you only use 3000 x 1500 and p leaves the first element unused. Perhaps the code is still correct, but at least your way of using indices is confusing. Also in case you know the size of the array only at runtime you could use a std::vector.

Project euler 55

I was solving this problem (https://projecteuler.net/problem=55) and I couldn't get it right. The answer was 249 and my code was giving 136. I don't know what is wrong with my code. Here is my code:
#include <stdio.h>
long long reverse(long long n)
{
long long a=0, t=n, temp;
while (t)
{
temp=t%10;
a=a*10+temp;
t=t/10;
}
return a;
}
bool palindromic(long long n)
{
return reverse(n)==n;
}
bool lychrel(long long n)
{
long long k=n;
for (int i=0; i<50; i++)
{
k+=reverse(k);
if (palindromic(k)) return false;
}
return true;
}
int main()
{
int i, count=0;
for (i=1; i<10000; i++)
if (lychrel(i)) count++;
printf("%d", count);
return 0;
}
Thanks in advance!
When you apply the k+=reverse(k); it is overflowing for many of the Lychrel numbers.
For example 196 overflows after 40 iterations.
To be able to test if some number is a Lychrel you need more than the 64 bits the long long provides (63 bits to be more precise). You need to either use big integers or string manipulation if you want to do the "add" manually for 2 strings.
Check this answer for big integers: C++ Big Integer
If you want a quick and dirty fix, you can just test for overflow and consider that if it overflows, it needs "too many" iterations. This will not be a correct program (because it will not test for 50 iterations), but will still give you a correct result (because you will be able to find all the non Lychrel numbers below ten thousand before they overflow). It will for sure fail if you increase the limit from ten thousand to some bigger numbers.
To test for overflow you can just check if k + reverse(k) < k for example.

Optimizing a recursive function

I'm creating a program that returns the least quantity of sums required to get to a number (n) using only 1, 2, 6 and 13. It works perfectly for small values of n, but once n gets to values like 200 it takes the program too much time to calculate the result.
Therefore, I have two questions:
1. Is there any way to make the recursion faster?
2. Should I avoid using recursion and use a loop instead?
Here's the commented code:
#include <iostream>
#define MAX 500000
using namespace std;
void cal(int inp, int &mini, int counter = 0);
int main (void)
{
//Gets input
int n;
cin >> n;
//Defines mini as the MAX result we can get
int mini = MAX;
//Calls the function
cal(n, mini);
//Prints the best result
cout << mini << endl;
return 0;
}
void cal(int inp, int &mini, int counter)
{
//Breaks recursion if it finds an answer
if(!inp)
{
if(counter<mini) mini = counter;
return;
}
//Breaks recursion if the input is negative
//or the counter is more than the best result
else if((inp<0) || (counter>mini)) return;
//Counts amount of recursions
counter++;
//Tries every combination
cal(inp-13, mini, counter);
cal(inp-6, mini, counter);
cal(inp-2, mini, counter);
cal(inp-1, mini, counter);
return;
}
Thank you
The problem is your brute force. Let me suggest something better:
Preliminaries: If you have two 1s, it is always better to use a 2. If you have three 2s, it is better to use a 6. If you have thirteen 6s, it is better to use six thirteens.
So the any admissable sum will always look like n = 13m+k where k is written as a sum of 1, 2, and 6. With the preliminaries, we know that for the optimal sum k will never exceed 1+2*2+12*6 = 77. (The reverse doesn't hold. Not any number below 78 is best written without 13s of course.) So brute forcing those is good enough. You can then use a lookup table.
This could still be optimized further, but it should not break down at 200.
Assuming you have found your first 77 entries (which can be optimized as well) you can do this (still unoptimized ;-):
int num_13 = ((n-78) / 13) + 1;
int sum_length = MAX;
for (i = num_13; i*13 < n; i++) {
int tmp = entries_77[n-i*13]+i;
if (tmp < sum_length) {
num_13 = i;
sum_length = tmp;
}
}
I would be even quicker to compile an array for the equivalence classes modulo 13, since for any given equivalence class any number exceeding 78 will have the same k.
You can use DP (Dynamic Programming) approach to solve your problem. It's well known Coins Problem
Your recursion needs a memoization to avoid repetitive calculation. And no need for the second and third parameter of the recursion. I have updated and put explanation on your code. Let me know if you have any confusion.
#include <iostream>
#include <string.h>
#define INF 999999
using namespace std;
int cal(int inp);
int mem[502];
int main (void)
{
//Gets input
int n;
cin >> n;
//initialzing the array for using with memoization
memset(mem,-1,sizeof(mem));
//Calls the function
//Prints the best result
cout << cal(n) << endl;
return 0;
}
//returns the minimum quantity of sum operations to get inp.
int cal(int inp)
{
//Breaks recursion if it finds an answer.
//Return cost 0. As in this stage no processing was done.
if(!inp)
return 0;
// Returning infinite cost for invalid case.
if(inp < 0)
return INF;
int _ret = mem[inp];
// If already visited here before then no need to calcuate again.
// Just return previous calculation. This is called memoisation.
// If not visited then _ret would have equal to -1.
if(_ret >=0 )
return _ret;
_ret = INF;
//Tries every combination and takes the minimum cost.
_ret = min(_ret, cal(inp-13)+1);
_ret = min(_ret,cal(inp-6)+1);
_ret = min(_ret,cal(inp-2)+1);
_ret = min(_ret,cal(inp-1)+1);
// Updating the value so that can be used for memoization.
mem[inp] = _ret;
return _ret;
}
This will also work for larger numbers. Complexity is 4*n.

finding the number of perfect squares in the given range

I am trying to find out the number of perfect squares in the given range. The method I am following is provided on: digital_root
The code I have implemented is not giving correct answers sometimes because This method does not consider the numbers like 10,1000 etc.
Please help me to work out this method.
int cot=0;
void squares(int a,int b){
if(a==b){
int digit,digit_root=0,no;
no=a;
digit=no%10;
if(digit==2||digit==3||digit==7||digit==8){
}else{
no=a;
while(no>0){
digit=no%10;
if((digit==0)||(digit==9)){
}else{
digit_root=digit_root+digit;
digit_root=digit_root%9;
}
no=no/10;
}
if(digit_root==0||digit_root==7||digit_root==1||digit_root==4){
if(digit_root==1){
if(a)
}
cot++;
}
}
}else{
int c=(a+b)/2;
squares(a,c);
squares(c+1,b);
}
}
int main() {
int a,b,t;
cin>>t;
for(int i=0;i<t;i++){
cin >> a>>b;
squares(a,b);
cout << cot<<endl;
cot=0;
}
return 0;
}
the best algorithm will probably be to subtract sqrt(bigger number) - sqrt(other num), i.e. something like this
int a = 1,b=100;
if (sqrt(a) != int(sqrt(a)){
cout<<int(sqrt(b))-int(sqrt(a))<<endl;}
else{
cout<<int(sqrt(b))-int(sqrt(a))+1<<endl;}
the logic is very simple, perfect square is natural num * the same natural num so, 1*1,2*2,3*3,4*4 and so on
So you just need to get the closest perfect sqrt of the bigger num and subtract it with the smaller num (just be careful in case that the smallest num is a perfect square itself)
There's too much going on here. Simplify it. Write a function that determines whether a single number is a perfect square. Get that working right. Then use that function to determine how many perfect squares there are in your range. That probably shouldn't be recursive; that's just too hard to follow. Use a loop that covers the range:
for (int i = a; i <= b; ++i)
if (is_perfect_square(i))
++count;
It's easy to print numbers from 1 to N, and the numbers will be perfect square.
Here is the logic to check perfect square
/*function definition to check perfect square*/
int isPerfectSquare(int number)
{
int iVar;
float fVar;
fVar=sqrt((double)number);
iVar=fVar;
if(iVar==fVar)
return 1;
else
return 0;
}
You dont need all these costly calculations.
Things are really simple here.
Instead of looping from A to B and checking for perfect squares,
we can calculate the first integer square root of A at O(1) and
count the rest perfect squares with simple increments of power n,
up to B. In this way we can avoid costly calculations.
But even better, we can even avoid loops by just using ceil and floor.
For example, square numbers between 1000 and 2000:
sqrt(1000) = 31.6 --> ceil(31.6) --> 32
sqrt(2000) = 44.7 --> floor(44.7)--> 44
therefore the difference of these two plus one gives us the number of perfect squares.
#include <cmath>
#include <iostream>
using namespace std;
int main() {
int A, B;
//get the range [A,B]
cin >> A >> B;
cout << floor(sqrt(B)) - ceil(sqrt(A)) + 1 << end;
return 0;
}

Output wrong Project Euler 7

So I'm trying out Problem 7 of Project Euler.
By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.
What is the 10 001st prime number?
#include <iostream>
#include <cmath>
using namespace std;
bool isPrime(int a){
if (a==2||a==3){
return true;
}
if (a%2==0){
return false;
}
bool prime=true;
for (int b=2;b<sqrt(a);b++){
if (a%b==0)
prime=false;
}
if (prime==true)
return true;
else
return false;
}
int main(){
int infinite=0;
long long int primecounter=0;
for (int c=2;infinite==0;c++){
if (isPrime(c)==true){
primecounter++;
//cout<<c<<endl;
if (primecounter==10001)
{cout<<c;
break;}
}
}
return 0;}
This is what I've come up with so far. It works for the few numbers that I tested, like the 6th prime number etc. However, when I run it for the 10001st prime, it gives me 104021, and the answer is wrong. Can someone tell me what is wrong with my code?
Where you get it wrong is b < sqrt(a). Think of a=25, what happens in this case?
rest of answer already pointed by comments.
Although this is not required for this specific problem, you should take a look at Sieve of Eratosthenes algorithm. You will need it sooner or later to solve prime related problems.
You can solve it without getting help from 'cmath' too.Logic is like...
To check whether a number is prime, set a counter variable to 0; write a loop to divide the number by every number less than it till 1. If a number completely divides it, the counter will increase by one; the counetr will be exactly 2 for a prime number.
To calculate sucha big number u should choose a proper datatype too.I have used 'long long int' as a datatype.
My code for the project euler problem no 7 is as follows.Hope it helps you.Best wishes.Editions and improvements in this program are most welcome.Only bug is the time that it consumes,it takes more than an hour to reach the 10001th prime number.
#include<iostream.h>
#include<conio.h>
class prime
{
long long int a;
long long int j,i;
public:
void display();
};
void prime::display()
{
j=0;
long long int count=0;
long long int count1=0;
while(count1!=10001)
{
j=j+1;
i=j;
while(i!=0)
{
if(j%i==0)
{
count++;
}
i--;
}
if(count==2)
{
count1++;
cout<<count1<<"\t"; //The serial number of the prime number.
cout<<j<<"\t";// This will diaply all prime numbers till 10001.
}
if(count1==10001)
{
cout<<"\nThe 10001th prime number is:"<<j;
}
count=0;
}
}
void main()
{
prime k;
clrscr();
k.display();
getch();
}