Summing Large Numbers - c++

I have being doing some problems on the Project Euler website and have come across a problem. The Question asks,"Work out the first ten digits of the sum of the following one-hundred 50-digit numbers." I am guessing there is some mathematical way to solve this but I was just wondering how numbers this big are summed? I store the number as a string and convert each digit to a long but the number is so large that the sum does not work.
Is there a way to hold very large numbers as a variable (that is not a string)? I do not want the code to the problem as I want to solve that for myself.

I was just wondering how numbers this big are summed?
You can use an array:
long LargeNumber[5] = { < first_10_digits>, < next_10_digits>....< last_10_digits> };
Now you can calculate the sum of 2 large numbers:
long tempSum = 0;
int carry = 0;
long sum[5] = {0,0,0,0,0};
for(int i = 4; i >= 0; i--)
{
tempSum = largeNum1[i] + largeNum2[i] + carry; //sum of 10 digits
if( i == 0)
sum[i] = tempSum; //No carry in case of most significant digit
else
sum[i] = tempSum % 1000000000; //Extra digits to be 'carried over'
carry = tempSum/1000000000;
}
for( int i = 0; i < 5; i++ )
cout<<setw(10)<<setfill('0')<<sum[i]<<"\n"; //Pad with '0' on the left if needed
Is there a way to hold very large numbers as a variable (that is not a
string)?
There's no primitive for this, you can use any data structure (arrays/queues/linkedlist) and handle it suitably
I am guessing there is some mathematical way to solve this
Of course! But,
I do not want the code to the problem as I want to solve that for myself.

You may store the digits in an array. To save space and increase performance in the operations, store the digits of the number in base 10^9. so a number
182983198432847829347802092190
will be represented as the following in the array
arr[0]=2092190
arr[1]=78293478 arr[2]=19843284 arr[3]=182983
just for the sake of clarity, the number is represented as summation of arr[i]*(10^9i)
now start with i=0 and start adding the numbers the way you learnt as a kid.

I have done in java, Here I am taking to numbers N1 and N2, And I have create an array of size 1000. Lets take an example How to solve this, N1=12, N2=1234. For N1=12, temp=N1%10=2, Now add this digit with digit N2 from right to Left and store the result into array starting from i=0, similarly for rest digit of N1. The array will store the result but in reverse order. Have a looking on this link. Please check this link http://ideone.com/V5knEd
import java.util.*;
import java.lang.*;
import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
public static void main (String[] args) throws java.lang.Exception {
Scanner scan=new Scanner(System.in);
int A=scan.nextInt();
int B=scan.nextInt();
int [] array=new int[1000];
Arrays.fill(array,0);
int size=add(A,B,array);
for(int i=size-1;i>=0;i--){
System.out.print(array[i]);
}
}
public static int add(int A, int B, int [] array){
int carry=0;
int i=0;
while(A>0 || B>0){
int sum=A%10+B%10+carry+array[i];
array[i]=sum%10;
carry=sum/10;
A=A/10;
B=B/10;
i++;
}
while(carry>0){
array[i]=array[i]+carry%10;
carry=carry/10;
i++;
}
return i;
}
}

#include<iostream>
#include<fstream>
#include<sstream>
using namespace std;
struct grid{
int num[50];
};
int main()
{
struct grid obj[100];
char ch;
ifstream myfile ("numbers.txt");
if (myfile.is_open())
{
for(int r=0; r<100; r++)
{
for(int c=0; c<50; c++)
{
myfile >> ch;
obj[r].num[c] = ch - '0';
}
}
myfile.close();
int result[50],temp_sum = 0;
for (int c = 49; c>=0; c--)
{
for (int r=0; r<100; r++)
{
temp_sum += obj[r].num[c];
}
result[c] = temp_sum%10;
temp_sum = temp_sum/10;
}
string temp;
ostringstream convert;
convert << temp_sum;
temp = convert.str();
cout << temp_sum;
for(unsigned int count = 0; count < (10 - temp.length()); count++)
{
cout << result[count];
}
cout << endl;
}
return 0;
}

This the best way for your time and memory size :D
#include <iostream >
#include <climits >
using namespace std;
int main()
{
unsigned long long z;
cin >>z;
z=z*(z+1)/2;
C out << z;
return 0;
}

Related

C++: How to Generate All Combinations of a Vector of Digits of Length N, disregarding order?

So I need to combine a specific number (not string) of digits from a vector of possible ones (all 0-9, not characters) in an N-digit number (not binary, then). However, I cannot have any extra permutations appear: for example 1234, 4321, 3124... are now the same and cannot be all outputed. Only one can be. This is hard because other questions cover these permutions by using std::next_permutation, but I still need the different combinations. My attempts at trying to remove permutations have failed, so how do you do this? Here is my current code with comments:
#include <iostream>
#include <vector>
using namespace std;
#define ll long long
int n = 0, m = 0, temp; //n is number of available digits
//m is the length of the desired numbers
//temp is used to cin
vector <int> given;
//vector of digits that can be used
vector <int> num;
//the vector to contain a created valid number
void generate(vector <int> vec, int m) {
//recursive function to generate all numbers
if (m == 0) {
for (int x : num) {
cout << x;
}
cout << '\n';
return;
}
for (int i = 0; i < given.size(); i++) {
num.push_back(given[i]); //add digit to number
int save = given[i];
given.erase(given.begin() + i);
//no repeating digits, save the used one and delete
//however, permutations can still pass, which is undesirable
generate(vec, m - 1);
//recursive
num.pop_back();
//undo move
given.insert(given.begin() + i, save);
//redo insert deleted digit
}
}
int main () {
cin >> n;
//input number of available digits
for (int i = 0; i < n; i++) {
cin >> temp;
given.push_back(temp); //input digits
}
cin >> m;
//input length of valid numbers
generate(given, m); //start recursive generation function
return 0;
}
I tried deleting permutations before printing them and erasing more digits to stop generating permutations, but they all failed. Lots of other questions still used std::next_permutation, which was not helpful.
Unlike some people who suggested binary strings in some comments, you can begin by having a recursive function that can go two ways as an on/off switch to decide whether or not to include a given digit. I personally like using a recursive function to do this and a check for length at the end to actually print the number of the desired len, demonstrated in the code below:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int givencount = 0, temp = 0, len = 0;
vector <int> given;
string creatednum;
void generate(int m) {
if (m == givencount) {
if (creatednum.length() == len) {
cout << creatednum << '\n';
}
return;
}
for (int i = 0; i < 2; i++) {
if (i == 1) {
generate(m + 1);
continue;
}
creatednum = creatednum + ((char) ('0' + given[m]));
generate(m + 1);
creatednum.erase(creatednum.begin() + creatednum.length() - 1);
}
}
int main () {
cin >> givencount;
for (int i = 0; i < givencount; i++) {
cin >> temp;
given.push_back(temp);
}
cin >> len;
generate(0);
return 0;
}

(C++) Generate first p*n perfect square numbers in an array (p and n inputted from the keyboard)

I input p and n (int type) numbers from my keyboard, I want to generate the first p*n square numbers into the array pp[99]. Here's my code:
#include <iostream>
#include <math.h>
using namespace std;
int main()
{
int i, j, n, p, pp[19];
cout<<"n="; cin>>n;
cout<<"p="; cin>>p;
i=n*p;
j=-1;
while(i!=0)
{
if(sqrt(i)==(float)sqrt(i))
{
j++;
pp[j]=i;
}
i--;
}
for(i=0; i<n*p; i++)
cout<<pp[i]<<" ";
return 0;
}
But I am encountering the following problem: If I for example I enter p=3 and n=3, it will only show me the first 3 square numbers instead of 9, the rest 6 being zeros. Now I know why this happens, just not sure how to fix it (it's checking the first n * p natural numbers and seeing which are squares, not the first n*p squares).
If I take the i-- and add it in the if{ } statement then the algorithm will never end, once it reaches a non-square number (which will be instant unless the first one it checks is a perfect square) the algorithm will stop succeeding in iteration and will be blocked checking the same number an infinite amount of times.
Any way to fix this?
Instead of searching for them, generate them.
int square(int x)
{
return x * x;
}
int main()
{
int n = 0;
int p = 0;
std::cin >> n >> p;
int limit = n * p;
int squares[99] = {};
for (int i = 0; i < limit; i++)
{
squares[i] = square(i+1);
}
for (int i = 0; i < limit; i++)
{
std::cout << squares[i] << ' ';
}
}

Modifying a dynamic 2D array in a function

I've got a function that accepts a dynamic multidimensional array (which is initialized to 0) as a parameter, and I'm trying to modify certain values within the array in my function.
The function that accepts the array as a parameter is supposed to simulate the roll of two dice and output the frequency distribution to the array I made that's initialized to zero.
The code for it is as follows:
#include <iostream>
#include <cstdlib>
using namespace std;
int** rollDie(int numRolls, unsigned short seed, int** &rollarray)
{
srand(seed);
int side1, side2;
while (numRolls > 0)
{
side1 = 1 + rand() % 6;
side2 = 1 + rand() % 6;
rollarray[side1][side2]++;
numRolls--;
}
return rollarray;
}
int** initializeArray(void)
{
int i, j;
int** m = new int*[6];
for (i = 0; i < 6; i++)
m[i] = new int[6];
for (i = 0; i < 6; i++)
for (j = 0; j < 6; j++)
m[i][j] = 0;
return m;
}
int main()
{
int numRolls;
unsigned short seed;
int ** a = initializeArray();
cout << "rolls?\n";
cin >> numRolls;
cout << "seed?\n";
cin >> seed;
int ** b = rollDie(numRolls, seed, a);
int i,j;
for (i = 0; i < 6; i++) {
for (j = 0; j < 6; j++) {
cout << b[i][j];
}
cout << "\n";
}
}
Code works for me with just a few issues (I had to guess how you defined a. Next time add that too):
In the printing you should print a space after every number (minor)
In the random, you choose index as 1+rand()%6, so from 1 to 6, but when you print you take indexes from 0 to 5! So your first row and first column will be 0.
Other than that it seems to work.
Only when one goes and does something else does the answer come to mind. I suspect you declared a as:
int a[6][6];
which is an array of 36 integers. In your function, though, you're declaring rollarray to be a pointer to an array of pointers to integers. All you need to do is change the function signature to:
int* rollDie(int numRolls, unsigned short seed, int* rollarray)
As cluracan said, you also want to use array indices in the range 0 to 5.
This is a good case for either the judicious use of print statements or stepping through with a debugger to see what's really going on.

Extremely slow random string generator

I came up with the below code to generate 100001 random strings.the strings should be unique. However, the below code takes hours to do the job. Can someone let me know how i can optimize it and why is it so slow?
string getRandomString(int length) {
static string charset = "abcdefghijklmnopqrstuvwxyz";
string result;
result.resize(length);
for (int i = 0; i < length; i++) {
result[i] = charset[rand() % charset.length()];
}
return result;
}
void main(){
srand(time(NULL));
vector<string> storeUnigrams;
int numUnigram = 100001;
string temp = "";
int minLen = 3;
int maxLen = 26;
int range = maxLen - minLen + 1;
int i =0;
while(i < numUnigram){
int lenOfRanString = rand()%range + minLen;
temp = getRandomString(lenOfRanString);
bool doesithave = false;
for(int j =0 ; j < storeUnigrams.size() ; j++){
if(temp.compare(storeUnigrams[j]) == 0){
doesithave = true;
break;
}
if(temp.compare(storeUnigrams[j]) < 0){
break;
}
}
if(!doesithave){
storeUnigrams.push_back(temp);
sort(storeUnigrams.begin(),storeUnigrams.end());
i++;
}
}
There are two factors that make your code slow:
Checking by linear search whether the string already exists – O(n)
Sorting the vector in each iteration – O(n log n)
Use e.g. a set for storing the strings – it's sorted automatically, and checking for existence is fast:
int main(){
srand(time(NULL));
set<string> storeUnigrams;
int numUnigram = 100001;
int minLen = 3;
int maxLen = 26;
int range = maxLen - minLen + 1;
while(storeUnigrams.size() < numUnigram){
int lenOfRanString = rand()%range + minLen;
storeUnigrams.insert(getRandomString(lenOfRanString));
}
}
This code generates a unique random number only once and stores it in random_once[i].
The first for loop generates ad stores the random number.
The second for loop is used to get the pre-rendered random numbers stored in the random_once[i] array.
Yes generating 100001 random numbers will take hours if not days.
#include <ctime>
#include <iostream>
using namespace std;
int main()
{
int numUnigram = 3001;
int size=numUnigram;
int random_once[100001];
cout<<"Please wait: Generatng "<<numUnigram<<" random numbers ";
std::cout << '-' << std::flush;
srand(time(0));
for (int i=0;i<size;i++)
{
//This code generates a unique random number only once
//and stores it in random_once[i]
random_once[i]=rand() % size;
for(int j=0;j<i;j++) if (random_once[j]==random_once[i]) i--;
//loading animation
std::cout << "\b\\" << std::flush;
std::cout << "\b|" << std::flush;
std::cout << "\b/" << std::flush;
std::cout << "\b-" << std::flush;
}
cout<<" \n";
// this code dispays unique random numbers stored in random_once[i]
for ( i=0;i<size;i++) cout<<" "<<random_once[i]<<"\t";
cout<<" \n";
return 0;
}
Philipp answer is fine. Another approach would be to use a Self-balancing Binary Search Tree like Red Black Tree instead of Vector. You can perform search and insets in log(n) time. If search is empty, insert the element.
Define your variables outside the while loop - because they are getting redefined at each iteration
int lenOfRanString = rand()%range + minLen; ;
bool doesithave = false;
Update
Thought it's advised in many books, in practice with all the new compilers, this will not significantly improve the performance
Use char arrays instead of strings (the string class does a lot of stuff behind the scenes)

Codechef practice question help needed - find trailing zeros in a factorial

I have been working on this for 24 hours now, trying to optimize it. The question is how to find the number of trailing zeroes in factorial of a number in range of 10000000 and 10 million test cases in about 8 secs.
The code is as follows:
#include<iostream>
using namespace std;
int count5(int a){
int b=0;
for(int i=a;i>0;i=i/5){
if(i%15625==0){
b=b+6;
i=i/15625;
}
if(i%3125==0){
b=b+5;
i=i/3125;
}
if(i%625==0){
b=b+4;
i=i/625;
}
if(i%125==0){
b=b+3;
i=i/125;
}
if(i%25==0){
b=b+2;
i=i/25;
}
if(i%5==0){
b++;
}
else
break;
}
return b;
}
int main(){
int l;
int n=0;
cin>>l; //no of test cases taken as input
int *T = new int[l];
for(int i=0;i<l;i++)
cin>>T[i]; //nos taken as input for the same no of test cases
for(int i=0;i<l;i++){
n=0;
for(int j=5;j<=T[i];j=j+5){
n+=count5(j); //no of trailing zeroes calculted
}
cout<<n<<endl; //no for each trialing zero printed
}
delete []T;
}
Please help me by suggesting a new approach, or suggesting some modifications to this one.
Use the following theorem:
If p is a prime, then the highest
power of p which divides n! (n
factorial) is [n/p] + [n/p^2] +
[n/p^3] + ... + [n/p^k], where k is
the largest power of p <= n, and [x] is the integral part of x.
Reference: PlanetMath
The optimal solution runs in O(log N) time, where N is the number you want to find the zeroes for. Use this formula:
Zeroes(N!) = N / 5 + N / 25 + N / 125 + ... + N / 5^k, until a division becomes 0. You can read more on wikipedia.
So for example, in C this would be:
int Zeroes(int N)
{
int ret = 0;
while ( N )
{
ret += N / 5;
N /= 5;
}
return ret;
}
This will run in 8 secs on a sufficiently fast computer. You can probably speed it up by using lookup tables, although I'm not sure how much memory you have available.
Here's another suggestion: don't store the numbers, you don't need them! Calculate the number of zeroes for each number when you read it.
If this is for an online judge, in my experience online judges exaggerate time limits on problems, so you will have to resort to ugly hacks even if you have the right algorithm. One such ugly hack is to not use functions such as cin and scanf, but instead use fread to read a bunch of data at once in a char array, then parse that data (DON'T use sscanf or stringstreams though) and get the numbers out of it. Ugly, but a lot faster usually.
This question is from codechef.
http://www.codechef.com/problems/FCTRL
How about this solution:
#include <stdio.h>
int a[] = {5, 25, 125, 625, 3125, 15625, 78125, 390625, 1953125, 9765625, 48828125, 244140625};
int main()
{
int i, j, l, n, ret = 0, z;
scanf("%d", &z);
for(i = 0; i < z; i++)
{
ret = 0;
scanf("%d", &n);
for(j = 0; j < 12; j++)
{
l = n / a[j];
if(l <= 0)
break;
ret += l;
}
printf("%d\n", ret);
}
return 0;
}
Any optimizations???
Knows this is over 2 years old but here's my code for future reference:
#include <cmath>
#include <cstdio>
inline int read()
{
char temp;
int x=0;
temp=getchar_unlocked();
while(temp<48)temp=getchar_unlocked();
x+=(temp-'0');
temp=getchar_unlocked();
while(temp>=48)
{
x=x*10;
x+=(temp-'0');
temp=getchar_unlocked();
}
return x;
}
int main()
{
int T,x,z;
int pows[]={5,25,125,625,3125,15625,78125,390625,1953125,9765625,48828125,244140625};
T=read();
for(int i=0;i<T;i++)
{
x=read();
z=0;
for(int j=0;j<12 && pows[j]<=x;j++)
z+=x/pows[j];
printf("%d\n",z);
}
return 0;
}
It ran in 0.13s
Here is my accepted solution. Its score is 1.51s, 2.6M. Not the best, but maybe it can help you.
#include <iostream>
using namespace std;
void calculateTrailingZerosOfFactoriel(int testNumber)
{
int numberOfZeros = 0;
while (true)
{
testNumber = testNumber / 5;
if (testNumber > 0)
numberOfZeros += testNumber;
else
break;
}
cout << numberOfZeros << endl;
}
int main()
{
//cout << "Enter number of tests: " << endl;
int t;
cin >> t;
for (int i = 0; i < t; i++)
{
int testNumber;
cin >> testNumber;
calculateTrailingZerosOfFactoriel(testNumber);
}
return 0;
}
#include <cstdio>
int main(void) {
long long int t, n, s, i, j;
scanf("%lld", &t);
while (t--) {
i=1; s=0; j=5;
scanf("%lld", &n);
while (i != 0) {
i = n / j;
s = s + i * (2*j + (i-1) * j) / 2;
j = j * 5;
}
printf("%lld\n", s);
}
return 0;
}
You clearly already know the correct algorithm. The bottleneck in your code is the use of cin/cout. When dealing with very large input, cin is extremely slow compared to scanf.
scanf is also slower than direct methods of reading input such as fread, but using scanf is sufficient for almost all problems on online judges.
This is detailed in the Codechef FAQ, which is probably worth reading first ;)