i came across the following program for calculating large factorials(numbers as big as 100).. can anyone explain me the basic idea used in this algorithm??
I need to know just the mathematics implemented in calculating the factorial.
#include <cmath>
#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
unsigned int d;
unsigned char *a;
unsigned int j, n, q, z, t;
int i,arr[101],f;
double p;
cin>>n;
p = 0.0;
for(j = 2; j <= n; j++)
p += log10(j);
d = (int)p + 1;
a = new unsigned char[d];
for (i = 1; i < d; i++)
a[i] = 0; //initialize
a[0] = 1;
p = 0.0;
for (j = 2; j <= n; j++)
{
q = 0;
p += log10(j);
z = (int)p + 1;
for (i = 0; i <= z/*NUMDIGITS*/; i++)
{
t = (a[i] * j) + q;
q = (t / 10);
a[i] = (char)(t % 10);
}
}
for( i = d -1; i >= 0; i--)
cout << (int)a[i];
cout<<"\n";
delete []a;
return 0;
}
Note that
n! = 2 * 3 * ... * n
so that
log(n!) = log(2 * 3 * ... * n) = log(2) + log(3) + ... + log(n)
This is important because if k is a positive integer then the ceiling of log(k) is the number of digits in the base-10 representation of k. Thus, these lines of code are counting the number of digits in n!.
p = 0.0;
for(j = 2; j <= n; j++)
p += log10(j);
d = (int)p + 1;
Then, these lines of code allocate space to hold the digits of n!:
a = new unsigned char[d];
for (i = 1; i < d; i++)
a[i] = 0; //initialize
Then we just do the grade-school multiplication algorithm
p = 0.0;
for (j = 2; j <= n; j++) {
q = 0;
p += log10(j);
z = (int)p + 1;
for (i = 0; i <= z/*NUMDIGITS*/; i++) {
t = (a[i] * j) + q;
q = (t / 10);
a[i] = (char)(t % 10);
}
}
The outer loop is running from j from 2 to n because at each step we will multiply the current result represented by the digits in a by j. The inner loop is the grade-school multiplication algorithm wherein we multiply each digit by j and carry the result into q if necessary.
The p = 0.0 before the nested loop and the p += log10(j) inside the loop just keep track of the number of digits in the answer so far.
Incidentally, I think there is a bug in this part of the program. The loop condition should be i < z not i <= z otherwise we will be writing past the end of a when z == d which will happen for sure when j == n. Thus replace
for (i = 0; i <= z/*NUMDIGITS*/; i++)
by
for (i = 0; i < z/*NUMDIGITS*/; i++)
Then we just print out the digits
for( i = d -1; i >= 0; i--)
cout << (int)a[i];
cout<<"\n";
and free the allocated memory
delete []a;
Related
You have d dice, and each die has f faces numbered 1, 2, ..., f.
Return the number of possible ways (out of fd total ways) modulo 10^9 + 7 to roll the dice so the sum of the face up numbers equals target.
My code works well for small values of f,d and target. It gives 0 as answer for big values say 30, 30, 500.
I am getting a lot of difficulty solving where modulo occurs.
What is wrong with my solution ?
int numRollsToTarget(int d, int f, int target)
{
long long int dp[d][target];
for (int i = 0; i < d; i++)
{
for (int j = 0; j < target; j++)
{
dp[i][j] = 0;
}
}
for (int i = 0; i < f && i < target; i++)
{
dp[0][i] = 1;
}
for (int i = 1; i < d; i++)
{
for (int j = 0; j < target; j++)
{
if (j >= i)
for (int k = max(0, j - f); k < min(j, f); k++)
dp[i][j] = (dp[i - 1][j - k - 1] % 1000000007 +
dp[i][j] % 1000000007) % 1000000007;
}
}
return dp[d - 1][target - 1];
}
How do I solve following programming riddle in O(N)?
Array of integers: Tab[N]
Find max(Tab[K] - K + Tab[L] + L)
where 0 <= K <= L <= N
The only solution I can come up with is O(N^2) where I compare each element and update maximum sum.
int curr_max = INTEGER_MIN;
for(int i = 0; i < N; i++){
for(int j = i; j < N; j++){
curr_max = max(Tab[i]-i + Tab[j] + j,curr_max);
}
}
In general, a possible way to solve such kind of tasks, due to K<=L constraint, is to use pre-calculated running max. (The version below can be optimized, but anyway has O(N) time and space complexity.)
int t[N+1]; // input
int a[N+1]; // running max t[i]-i, left to right
a[0] = t[0]-0;
for (int i = 1; i <= N; ++i)
a[i] = max(a[i-1], t[i]-i);
int b[N+1]; // running max t[i]+i, right to left
b[N] = t[N]+N;
for (int i = N-1; i >= 0; --i)
b[i] = max(b[i+1], t[i]+i);
int mx = a[0] + b[0];
for (int i = 1; i <= N; ++i)
mx = max(mx, a[i] + b[i]);
However, in our case, it can be shown that if K: Tab[K]-K -> max and L: Tab[K]+K -> max then K<=L. In other words, if L and K are indices of the two maxima respectively, the property L<=K holds. Therefore, the naïve approach should work too:
int K = 0, L = 0;
for (int i = 1; i <= N; ++i) {
if (t[i]-i > t[K]-K)
K = i;
if (t[i]+i > t[L]+L)
L = i;
}
assert(K <= L);
int mx = t[K]-K + t[L]+L;
How about:
int L_max = INTEGER_MIN;
int K_max = INTEGER_MIN;
for(int i=0; i<N; i++)
{
K_max = max(Tab[i] -i, K_max);
L_max = max(Tab[i] +i, L_max);
}
curr_max = K_max + L_max;
Note that it does not validate K <= L, neither does the code in the question.
Suppose I have a point P in [0,1]*[0,1], and [0,1] is divided into m(say 200) grids. I use A[m][m] to indicate whether [a small square centred at P with length 2h] covers each grid or not. So for a point P, A[i][j] is either (increase by) 1 or 0.
Suppose I have n such points(P1,...,Pn), I want to calculate A(for each point Pi, I redo the above procedure, adding 1 or not). How can I do this efficiently(with C++) rather than writing 3 layers of for loops to check for each grid and each point(So O(nm^2))?
I tried the naive 3 for loops with C++. It takes longer time than using some of the vectorized operations(like vector<= number for comparing n numbers together, A[bool vector, bool vector] for subsetting) in R.
Since C++ is generally faster than R, is there any smart way to implement this process?
#include <Rcpp.h>
#include <cmath>
using namespace Rcpp;
// [[Rcpp::export]]
double myfun(NumericVector u, NumericVector v)
{
double n = u.size();
double A[200][200] = {0};
double pos[200];
int i = 0, j = 0, k = 0;
for (i = 0; i < 200; i++)
{
pos[i] = (double)i / 201;
}
for (k = 0; k < n; k++)
{
for (i = 0; i < 200; i++)
{
for (j = 0; j < 200; j++)
{
if ( (fabs(u[k] - pos[i]) <= h) && (fabs(v[k] - pos[j]) <=h ) )
{
A[i][j]++;
}
}
}
}
double s = 0, avg = 0;
for (i = 0; i <200; i++)
{
for (j = 0; j < 200; j++)
{
s += A[i][j];
}
}
avg = s / (200 * 200);
return (avg);
}
The two inner loops only determine index of the point in your grid. But you can compute the index directly:
int i = (int)(u[k]*200);
int j = (int)(v[k]*200);
You probably also need to check that i and j don't reach the index 200. This only happens though, when u[k] == 1.0 or v[k] == 1.0.
double n = u.size();
double A[200][200] = {0};
for (int k = 0; k < n; k++)
{
int i = (int)(u[k]*200);
int j = (int)(v[k]*200);
if (i == 200)
i = 199;
if (j == 200)
j = 199;
A[i][j]++;
}
I found this problem somewhere in a contest and haven't been able to come up with a solution yet.
The boy has apples and keeps in boxes. In one box no more than N/2.
How many methods he can put candies to boxes.
So what I'm trying to do is to implement solution using DP. Here is my code:
#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <unistd.h>
#include <vector>
#define size 1002
using namespace std;
long long a[size][size];
int n, k;
int main()
{
cin >> n >> k;
int kk = n/2;
for(int i = 0; i <= k; ++i)
a[0][i] = 1;
a[0][0] = 0;
for(int i = 0; i <= kk; ++i)
a[i][1] = 1;
for(int i = 1; i <= n; ++i) {
for(int j = 2; j <= k; ++j) {
int index = 0;
long long res = 0;
while(1) {
res += a[i-index][j - 1];
index += 1;
if(index == kk + 1 || i-index < 0)
break;
}
a[i][j] = res;
}
}
cout << a[n][k] << endl;
}
But the problem is that we have large numbers in input like:
2 ≤ N ≤ 1000 is a quantity of the candies, N - even; 2 ≤ S ≤ 1000 - is a quantity of small boxes.
So, for input like N = 1000 and S = 1000, I have to spent 5*10^8 operations. And the numbers are very big, so I have to use BigInteger arithmetics?
Maybe there is algorithm to implement the problem in linear time? Thanks and sorry for my English!
You can easily decrease the time complexity from O(kn^2) into O(nk) by the following observation:
for(int i = 1; i <= n; ++i) {
for(int j = 2; j <= k; ++j) {
int index = 0;
long long res = 0;
while(1) {
res += a[i-index][j - 1];
index += 1;
if(index == kk + 1 || i-index < 0)
break;
}
a[i][j] = res;
}
}
for each a[i][j], we can easily see that
a[i][j] = sum a[k][j - 1] with k from (i - n/2) to i
So, if we create an array sum to store the sum from all indexes of the previous step, we can reduce one for loop from the above nested loop
a[i][j] = sum[i] - sum[i - (n/2) - 1];
Pseudo code:
long long sum[n + 1];
for(int j = 2; j <= k; ++j) {
long long nxt[n + 1];
for(int i = 1; i <= n; ++i) {
int index = 0;
long long res = sum[i] - sum[i - (n/2) - 1];
a[i][j] = res;
nxt[i] = nxt[i - 1] + a[i][j];//Prepare the sum array for next step
}
sum = nxt;
}
Note: This above code is not handled the initialization step for array sum, as well as not handle the case when i < n/2. Those cases should be obvious to handle.
Update:
My below Java solution get accepted by using similar idea:
public static void main(String[] args) throws FileNotFoundException {
// PrintWriter out = new PrintWriter(new FileOutputStream(new File(
// "output.txt")));
PrintWriter out = new PrintWriter(System.out);
Scanner in = new Scanner();
int n = in.nextInt();
int s = in.nextInt();
BigInteger[][] dp = new BigInteger[n + 1][2];
BigInteger[][] count = new BigInteger[2][n + 1];
int cur = 1;
for (int i = 0; i <= n / 2; i++) {
dp[i][0] = BigInteger.ONE;
count[0][i] = (i > 0 ? count[0][i - 1] : BigInteger.ZERO)
.add(dp[i][0]);
}
for (int i = n / 2 + 1; i <= n; i++) {
dp[i][0] = BigInteger.ZERO;
count[0][i] = count[0][i - 1];
}
for (int i = 2; i <= s; i++) {
for (int j = 0; j <= n; j++) {
dp[j][cur] = dp[j][1 - cur].add((j > 0 ? count[1 - cur][j - 1]
: BigInteger.ZERO)
.subtract(j > n / 2 ? count[1 - cur][j - (n / 2) - 1]
: BigInteger.ZERO));
count[cur][j] = (j > 0 ? count[cur][j - 1] : BigInteger.ZERO)
.add(dp[j][cur]);
}
cur = 1 - cur;
}
out.println(dp[n][1 - cur]);
out.close();
}
I want to write Fibonacci number program, using dynamic array in function. If I want to initialize array in the function, where I must delete this array? Here is code:
#include <iostream>
using namespace std;
int* fibo(int);
int main()
{
int *fibonacci, n;
cout << "Enter how many fibonacci numbers you want to print: ";
cin >> n;
fibonacci = fibo(n);
for (int i = 0; i<n; i++)
cout << fibonacci[i] << " ";
//for (int i = 0; i < n; i++)
//delete w_fibo[i];
//delete[] w_fibo;
return 0;
}
int* fibo(int n)
{
int* w_fibo = new int[n];
if (n >= 0)
w_fibo[0] = 1;
if (n >= 1)
w_fibo[1] = 1;
for (int i = 1; i < n; i++)
w_fibo[i + 1] = w_fibo[i] + w_fibo[i - 1];
return w_fibo;
}
You don't have to initialize the array! a better dynamic Fibonacci presentation could be like this:
int fib2 (int n) {
int i = 1, j = 0;
for (int k = 0; k < n; k++) { // The loop begins to work real after one loop (k == 1). Sounds interesting!
j += i; // Adds the produced number to the last member of the sequence and makes a new sentence.
i = j - i; // Produces the number that should be added to the sequence.
}
return j;
}
and you can get the n-th fib number using this method. It's O(log(n)) so it's so efficient.`
int fib3 (int n) {
int i = 1, j = 0, k = 0, h = 1, t=0;
while (n > 0) {
if (n % 2) { // |
t = j * h; // |
j = i * h + j * k + t;
i = i * k + t;
}
t = h * h;
h = 2 * k * h + t;
k = k * k + t;
n /= 2;
}
return j;
}
If you allocate a std::vector<int> inside fibo() and reserve enough memory, and then return it by value, the memory allocation is taken care for you by the compiler:
#include <iostream>
#include <vector>
using namespace std;
std::vector<int> fibo(int n)
{
std::vector<int> w_fibo;
w_fibo.reserve(n);
if (n >= 0)
w_fibo[0] = 1;
if (n >= 1)
w_fibo[1] = 1;
for (int i = 1; i < n; i++)
w_fibo[i + 1] = w_fibo[i] + w_fibo[i - 1];
return w_fibo;
}
int main()
{
int n = 10;
std::vector<int> fibonacci = fibo(n);
for (int i = 0; i<n; i++)
cout << fibonacci[i] << " ";
}
Live Example.
NOTE: This is guaranteed to avoid needlessly copying in C++11 (move semantics) and is likely to do so in C++98 (copy-elision using the return-value-optimization).
This is an old question, but just in case someone happens to pass by this might be helpful.
If you need a efficient method to get the nth Fibonacci number, we have a O(1) time complexity procedure.
It is based on Binet's formula, which I think our friends over at math.se will be better at proving, so feel free to follow that link.
The formula itself is, given a=1.618 and b=-0.618 (these are approximate values)
the n-th term is (a^n - b^n)/2.236. A good way to round that off(since we are using approximate values) would be adding 0.5 and taking the floor function.
math.floor(((math.pow(1.618,n)-math.pow(-0.618,n))/2.236 + 0.5)