So I am attempting Problem 50 of project euler. (So close to level 2 :D) It goes like this:
The prime 41, can be written as the sum of six consecutive primes:
41 = 2 + 3 + 5 + 7 + 11 + 13
This is the longest sum of consecutive primes that adds to a prime below one-hundred.
The longest sum of consecutive primes below one-thousand that adds to a prime, contains 21 terms, and is equal to 953.
Which prime, below one-million, can be written as the sum of the most consecutive primes?
Here is my code:
#include <iostream>
#include <vector>
using namespace std;
int main(){
vector<int> primes(1000000,true);
primes[0]=false;
primes[1]=false;
for (int n=4;n<1000000;n+=2)
primes[n]=false;
for (int n=3;n<1000000;n+=2){
if (primes[n]==true){
for (int b=n*2;b<100000;b+=n)
primes[b]=false;
}
}
int basicmax,basiccount=1,currentcount,biggermax,biggercount=1,sum=0,basicstart,basicend,biggerstart,biggerend;
int limit=1000000;
for (int start=2;start<limit;start++){
//cout<<start;
sum=0;
currentcount=0;
for (int basic=start;start<limit&&sum+basic<limit;basic++){
if (primes[basic]==true){
//cout<<basic<<endl;
sum+=basic;currentcount++;}
if (primes[sum]&¤tcount>basiccount&&sum<limit)
{basicmax=sum;basiccount=currentcount;basicstart=start;basicend=basic;}
}
if (basiccount>biggercount)
{biggercount=basiccount;biggermax=basicmax;biggerend=basicend;biggerstart=basicstart;}
}
cout<<biggercount<<endl<<biggermax<<endl;
return 0;
}
Basically it just creates a vector of all primes up to 1000000 and then loops through them finding the right answer. The answer is 997651 and the count is supposed to be 543 but my program outputs 997661 and 546 respectively. What might be wrong?
It looks like you're building your primes vector wrong
for (int b=n*2;b<100000;b+=n)
primes[b]=false;
I think that should be 1,000,000 not 100,000. It might be better to refactor that number out as a constant to make sure it's consistent throughout.
The rest of it looks basically fine, although without testing it ourselves I'm not sure what else we can add. There's plenty of room for efficiency improvements: you do do a lot of repeated scanning of ranges e.g. there's no point starting to sum when prime[start] is false, you could build a second vector of just the primes for the summing etc. (Does project Euler have runtime and memory limit restrictions? I can't remember)
You are thinking about this the wrong way.
Generate the maximal sequence of primes such that their sum is less than 1,000,000. This is 2, 3, 5, ..., p. For some p.
Sum this sequence and test it for primality.
If it is prime terminate and return the sum.
A shorter sequence must be the correct one. There are exactly two ways of shortening the sequence and preserving the consecutive prime property - removing the first element or removing the last. Recurse from 2 with both of these sequences.
Related
I am working on a program which prints the number of pairs of prime numbers (within a range L and R) whose difference is 6, where 2 <= L < R <= 10^9.
eg.,
L=2 R=20
Ans: 4
Explanation: 4 pairs are there: {5, 11}, {7, 13}, {11, 17}, {13, 19}
So my approach is to first store all the prime numbers within the range and then find all the pairs.
In worst case, L=2 and R=10^9;
To get all the prime numbers I am using sieve of eratosthenes, but its time complexity is O(nloglogn) which is a problem and another problem is of space (space complexity is O(n)) [array of size 10^9 can not be there].
I am running this program over online IDE.
#include <bits/stdc++.h>
#define siz 1000000000
using namespace std;
int main()
{
vector<bool> prime(siz);
int i, j;
for(i=0;i<siz;i++)
{
prime[i]=false;
}
for(i=2;i*i<=siz;i++)
{
if(prime[i]==false)
{
for(j=i*i;j<=siz;j+=i)
{
prime[j]=true;
}
}
}
int ans=0;
for(i=0;i<siz;i++)
{
if(prime[i]==false)
{
ans++;
}
}
cout<<ans;
return 0;
}
Above program is a part of the whole program where I am just counting the number of prime numbers till 10^9 and the message by compiler is SIGTSTP and when I am reducing the siz to 10^8, it's running fine and the output is 5761455 which is correct (I have verified it from wikipedia).
You are trying to find the sexy primes (Wikipedia, MathWorld, OEIS) less than a billion; mathematicians call them sexy because they differ by six, which is sex in Latin. There are 6,849,047 such primes, according to OEIS.
There is no need to store all of the primes less than a billion; you only ever need three of them. You can enumerate the primes by a segmented sieve or by a generator. Both of those methods are given in a recent discussion here on Stack Overflow. That code is in Python, so you will have to port it to C++.
I used the code in Pari that is also mentioned at that discussion to calculate the sexy primes on my cell phone, finding them in 62 seconds. Who knew a cell phone had so much power!
Kim Walisch has a fast C++ prime generator here which is pretty straight forward. It shouldn't be hard to adapt it to solve the difference of 6 problem. Kim has another version which is faster and far more complex to handle really big sized prime problems.
Inputs are two values 1 <= m , n <= 10^12
i don't know why my code is taking soo long for large values . time limit is 1 sec. please suggest me some critical modifications.
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
unsigned long long m,n,count=0;
cin >> m >> n;
for (long long int i = 1; i <= ((min(m,n))/2)+1; i++) //i divided min(m,n) by 2 to make it efficient.
{
if ((m%i == 0) && (n%i == 0))
{
count++;
}
}
if (((n%m == 0) || (m%n == 0)) && (n!=m))
{
cout << count << endl;
}
printf("%lld",count); //cout<<count;
system("pause");
return 0;
}
Firstly
((min(m, n)) / 2) + 1
Is being calculated every iteration. But it's loop-invariant. In general loop invariant code can be calculated before the loop, and stored. It will add up, but there are obviously much better ways to improve things. I'll describe one below:
you can make this much faster by calculating how many common prime factors there are, and by dividing out any "found" primes as you go. e.g. if only one number is divisible by 5, and the other is not, you can divide that one by 5 and you still get the same answer for common factors. Divide m and n by any "found" numbers as you go through it. (but keep checking whether either is divisible by e.g. 2 and keep dividing before you go on).
e.g. if the two numbers are both divisible by 2, 3 and 5, then the number of ways those three primes can combine is 8 (2^3), treating the presence of each prime as a true/false thing. So each prime that occurs once multiplies the number of combos by 2.
If any of the primes occurs more than once, then it changes the equation slightly. e.g. if the two numbers are divisible by 4, 3, 5:
4 = 2^2, so you could have no "2s", 1 "2" or 2 "2s" in the combined factor, so the total combinations 3 x 2 x 2 = 12. So any prime that occurs "x" times, multiplies the total number of combos by "x+1".
So basically, you don't need to check for every actual factor, you just need to search for how many common prime factors there are, then work out how many combos that adds up to. Luckily you only need to store one value, "total_combos" and multiply it by the "x+1" value for each found number as you go.
And a handy thing is that you can divide out all primes as they're found, and you're guaranteed that the largest remaining prime to be found is no larger than the square root of the smallest remaining number out of m and n.
So to run you through how this would work, start with a copy of m and n, loop up to the sqrt of the min of those two (m and n will be reduced as the loop cycles through).
make a value "total_combos", which starts at 1.
Check for 2's first, find out how many common powers of 2 there are, add one to that number. Divide out ALL the 2's from m and n, even if they're not matched, because reducing down the number cuts the total amount you actually need to search. You count the 2's, add one, then multiply "total_combos" by that. Keep dividing m or n by two as long as either has a factor of 2 remaining.
Then check for 3's, find out how many common powers of 3 there are, add one, the multiply "total_combos" by that. Divide out any and all factors of 3 when you're doing this.
then check for 4's. Since 4 isn't prime and we got rid of all 2's already, there will be zero 4's. Add one to that = 1, then we times "total_combos" by 1, so it stays the same. We didn't need to check whether 4 was prime or not, the divisions we already did ensured it's ignored. Same for any power of 2.
then check for 5's. same deal as 2's and 3's. And so on. All the prime bases get divided out as you go, so whenever a value actually matches you can be sure it's a new prime.
stop the loop when it exceeds sqrt(max(m,n)) (EDITED: min is probably wrong there). But m and n here are the values that have had all the lower primes divided out, so it's much faster.
I hope this approach is helpful.
There is a better way to solve this problem.
All you have to do is take the GCD of two numbers. Now any number won't divide m & n if they are greater than their GCD. So all you to do is that run a loop till the i<=Math.sqrt(GCD(m,n)) and check if the m%i==0 and n%i==0 only. It will save a lot of nanosecs.
I tried to run this code but it shows time limit exceeded in few cases, how can i shorten the time?
I need to understand what I have used in my program for which time is taking much, like some functions etc.. I understand by improving the iteration and complexity i can reduce execution time but its not helping much.please help
The program is simple, I take point a and point b and calculate the numbers of all the palindrome numbers.
#include<stdio.h>
int ifpalin(int g)
{
int rev=0;
int tmp=g;
while(tmp>0)
{
rev=rev*10+(tmp%10);
tmp=tmp/10;
}
if(rev==g)
return 1;
else
return 0;
}
int findpalin(int a1,int b1)
{
int sm=0;
for(int i=a1;i<=b1;i++)
{
if (ifpalin(i)==1)
sm++;
}
printf("%d",sm);
printf("\n");
return 0;
}
int main()
{
int a,b,n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&a);
scanf("%d",&b);
findpalin(a,b);
}
return 0;
}
Your code is already pretty efficient (as an implementation of your algorithm, which is the thing that can be improved). These challenges want to you to find a "non-obvious", but more efficient, algorithm. I.e., in this particular case, you should not check every number between a and b.
There is another solution here, i.e. you can "know" the number of palidromes directly. Think about itĀ“like this:
With one digit, there are 10 palidromes [0, ..., 9],
With two digits, there are 9 palindromes [11, ..., 99].
With three digits, there are 9 possibilities where the first and last digit are equal [1, ..., 9]. For a viable palindrom, the middle has to be a palindrome as well. Since the middle has one digit, we know there are 10 possibilities for palindromes here and thus we have 9 * 10 = 90 palindromes with 3 digits.
With four digits, we got 9 * 10 (two-digit palindromes, 00 now also allowed) and with 5 digits 9 * 100 (3-digit p, starting with 0 allowed).
Thus you can derive a formula for n-digit numbers.
Then, you can directly derive the number for large streaks between a and b and only have to worry about which number of digits are relevant and how many numbers are lost in the beginning and end due to a and b not being 10^(n-1) and and 10^n - 1
Your int ifpalin(int g) fnction, for each given g, could be run in parallel because it seems like different input data for this function, has no effect on other data. you can run this function in parallel.
In int findpalin(int a1,int b1) function, there is a for loop which its complexity order is N, this is where you can run your threads. (each thread, runs function ifpalin). Of course, a good parallelism plan is needed.
You can run this function in some logical bunch, and aggregate the results.
On the other hand, any benchmark should be performed in release mode.
I hope it helps.
Excuse me if my writing in English is bad, and please correct me.
In ifpalin
Convert the number to string
Reverse the string
Compare with the original
If equal then it's a palindrome
See How to reverse an std::string?
Given a number N (<=10000), find the minimum number of primatic numbers which sum up to N.
A primatic number refers to a number which is either a prime number or can be expressed as power of prime number to itself i.e. prime^prime e.g. 4, 27, etc.
I tried to find all the primatic numbers using seive and then stored them in a vector (code below) but now I am can't see how to find the minimum of primatic numbers that sum to a given number.
Here's my sieve:
#include<algorithm>
#include<vector>
#define MAX 10000
typedef long long int ll;
ll modpow(ll a, ll n, ll temp) {
ll res=1, y=a;
while (n>0) {
if (n&1)
res=(res*y)%temp;
y=(y*y)%temp;
n/=2;
}
return res%temp;
}
int isprimeat[MAX+20];
std::vector<int> primeat;
//Finding all prime numbers till 10000
void seive()
{
ll i,j;
isprimeat[0]=1;
isprimeat[1]=1;
for (i=2; i<=MAX; i++) {
if (isprimeat[i]==0) {
for (j=i*i; j<=MAX; j+=i) {
isprimeat[j]=1;
}
}
}
for (i=2; i<=MAX; i++) {
if (isprimeat[i]==0) {
primeat.push_back(i);
}
}
isprimeat[4]=isprimeat[27]=isprimeat[3125]=0;
primeat.push_back(4);
primeat.push_back(27);
primeat.push_back(3125);
}
int main()
{
seive();
std::sort(primeat.begin(), primeat.end());
return 0;
}
One method could be to store all primatics less than or equal to N in a sorted list - call this list L - and recursively search for the shortest sequence. The easiest approach is "greedy": pick the largest spans / numbers as early as possible.
for N = 14 you'd have L = {2,3,4,5,7,8,9,11,13}, so you'd want to make an algorithm / process that tries these sequences:
13 is too small
13 + 13 -> 13 + 2 will be too large
11 is too small
11 + 11 -> 11 + 4 will be too large
11 + 3 is a match.
You can continue the process by making the search function recurse each time it needs another primatic in the sum, which you would aim to have occur a minimum number of times. To do so you can pick the largest -> smallest primatic in each position (the 1st, 2nd etc primatic in the sum), and include another number in the sum only if the primatics in the sum so far are small enough that an additional primatic won't go over N.
I'd have to make a working example to find a small enough N that doesn't result in just 2 numbers in the sum. Note that because you can express any natural number as the sum of at most 4 squares of natural numbers, and you have a more dense set L than the set of squares, so I'd think it rare you'd have a result of 3 or more for any N you'd want to compute by hand.
Dynamic Programming approach
I have to clarify that 'greedy' is not the same as 'dynamic programming', it can give sub-optimal results. This does have a DP solution though. Again, i won't write the final process in code but explain it as a point of reference to make a working DP solution from.
To do this we need to build up solutions from the bottom up. What you need is a structure that can store known solutions for all numbers up to some N, this list can be incrementally added to for larger N in an optimal way.
Consider that for any N, if it's primatic then the number of terms for N is just 1. This applies for N=2-5,7-9,11,13,16,17,19. The number of terms for all other N must be at least two, which means either it's a sum of two primatics or a sum of a primatic and some other N.
The first few examples that aren't trivial:
6 - can be either 2+4 or 3+3, all the terms here are themselves primatic so the minimum number of terms for 6 is 2.
10 - can be either 2+8, 3+7, 4+6 or 5+5. However 6 is not primatic, and taking that solution out leaves a minimum of 2 terms.
12 - can be either 2+10, 3+9, 4+8, 5+7 or 6+6. Of these 6+6 and 2+10 contain non-primatics while the others do not, so again 2 terms is the minimum.
14 - ditto, there exist two-primatic solutions: 3+11, 5+9, 7+7.
The structure for storing all of these solutions needs to be able to iterate across solutions of equal rank / number of terms. You already have a list of primatics, this is also the list of solutions that need only one term.
Sol[term_length] = list(numbers). You will also need a function / cache to look up some N's shortest-term-length, eg S(N) = term_length iif N in Sol[term_length]
Sol[1] = {2,3,4,5 ...} and Sol[2] = {6,10,12,14 ...} and so on for Sol[3] and onwards.
Any solution can be found using one term from Sol[1] that is primatic. Any solution requiring two primatics will be found in Sol[2]. Any solution requiring 3 will be in Sol[3] etc.
What you need to recognize here is that a number S(N) = 3 can be expressed Sol[1][a] + Sol[1][b] + Sol[1][c] for some a,b,c primatics, but it can also be expressed as Sol[1][a] + Sol[2][d], since all Sol[2] must be expressible as Sol[1][x] + Sol[1][y].
This algorithm will in effect search Sol[1] for a given N, then look in Sol[1] + Sol[K] with increasing K, but to do this you will need S and Sol structures roughly in the form shown here (or able to be accessed / queried in a similar manner).
Working Example
Using the above as a guideline I've put this together quickly, it even shows which multi-term sum it uses.
https://ideone.com/7mYXde
I can explain the code in-depth if you want but the real DP section is around lines 40-64. The recursion depth (also number of additional terms in the sum) is k, a simple dual-iterator while loop checks if a sum is possible using the kth known solutions and primatics, if it is then we're done and if not then check k+1 solutions, if any. Sol and S work as described.
The only confusing part might be the use of reverse iterators, it's just to make != end() checking consistent for the while condition (end is not a valid iterator position but begin is, so != begin would be written differently).
Edit - FYI, the first number that takes at least 3 terms is 959 - had to run my algorithm to 1000 numbers to find it. It's summed from 6 + 953 (primatic), no matter how you split 6 it's still 3 terms.
While practicing for programming competitions (like ACM, Code Jam, etc) I've met some problems that require me to generate all possible combinations of some vector elements.
Let's say that I have the vector {1,2,3}, I'd need to generate the following combinations (order is not important) :
1
2
3
1 2
1 3
2 3
1 2 3
So far I've done it with the following code :
void getCombinations(int a)
{
printCombination();
for(int j=a;j<vec.size();j++)
{
combination.pb(vec.at(j));
getCombinations(j+1);
combination.pop_back();
}
}
Calling getCombinations(0); does the job for me. But is there a better (faster) way? I've recently heard of bitmasking. As I understood it's simply for all numbers between 1 and 2^N-1 I turn that number into a binary where the 1s and 0s would represent whether or not that element is included in the combinations.
How do I implement this efficiently though? If I turn every number into binary the standard way (by dividing with 2 all the time) and then check all the digits, it seems to waste a lot of time. Is there any faster way? Should I keep on using the recursion (unless I run into some big numbers where recursion can't do the job (stack limit))?
The number of combinations you can get is 2^n, where n is the number of your elements. You can interpret every integer from 0 to 2^n -1 as a mask. In your example (elements 1, 2, 3) you have 3 elements and the masks would therefore be 000, 001, 010, 011, 100, 101, 110, and 111. Let every place in the mask represent one of your elements. For place that has a 1, take the corresponding element, otherwise if the place contains a 0, leave the element out. For example the the number 5 would be the mask 101 and it would generate this combination: 1, 3.
If you want to have a fast and relatively short code for it, you could do it like this:
#include <cstdio>
#include <vector>
using namespace std;
int main(){
vector<int> elements;
elements.push_back(1);
elements.push_back(2);
elements.push_back(3);
// 1<<n is essentially pow(2, n), but much faster and only for integers
// the iterator i will be our mask i.e. its binary form will tell us which elements to use and which not
for (int i=0;i<(1<<elements.size());++i){
printf("Combination #%d:", i+1);
for (int j=0;j<elements.size();++j){
// 1<<j shifts the 1 for j places and then we check j-th binary digit of i
if (i&(1<<j)){
printf(" %d", elements[j]);
}
}
printf("\n");
}
return 0;
}