ACM ICPC -Number Theory - c++

I was practising ACM ICPC past problems http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1030
I am not able to solve this problem and have completely no idea how to do it in an efficient way within the 3 seconds time limit.
I think this problem is based on Number theory, but don't know exactly what to do.
Thanks!

Although transformed into vector problems, three-dimensional vectors and so many variables are somewhat tricky, so we can first reduce dimensionality and change the original equation into:
A[1]* (s[1][2]-s[1][1], s[1][3]-s[1][1]) + a[2]* (s[2][2]- s[2][1], s[2][3]- s[2][1]) +.....+a[n]* (s[n][2]- s[n][1],..+a[n]*) = (()).
The two-dimensional vector is regarded as the vector starting from the origin in the plane coordinate system. If there are only two vectors, because a[i] is a non negative number, so the angle must be PI when there are only two vectors. N vectors can satisfy the above equation if the angle between the two adjacent vectors is not greater than PI. The code is not long, but it needs a mathematical thinking T_T
Here is the correct code.
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn=1000+5;
const double PI=acos(-1);
int main()
{
int n;
double A[maxn];
while(scanf("%d",&n),n)
{
int s1,s2,s3;
for(int i=0;i<n;i++)
{
scanf("%d%d%d",&s1,&s2,&s3);
A[i]=atan2(s2-s1,s3-s1);
}
sort(A,A+n);
double tmp=0;
for(int i=1;i<n;i++)
tmp=max(tmp,A[i]-A[i-1]);
tmp=max(tmp,A[0]-A[n-1]+2*PI);
if(tmp<=PI)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}

So I believe given:
(a1,b1,c1), (a2,b2,c2) ... (an,bn,cn)
You need to decide if there exists non-negative coefficients:
X = (x1,x2,...,xn)
such that
x1*a1 + x2*a2 + ... + xn*an ==
x1*b1 + x2*b2 + ... + xn*bn ==
x1*c1 + x2*c2 + ... + xn*cn
A little linear algebra is all it takes.
Hint: Try and construct an input with n == 4, such that all 4 xis are required to be positive to solve the problem (and it cannot be solved with just 3). Is this possible?

Related

Generate an exponentially-spaced list of numbers

I want to generate an exponentially-spaced list of numbers in C++, where the number of points and the bounds are known (just like Matlab's linspace or logspace, or Python's numpy.logspace). I have found several implementations for log-spaced numbers (see below), but couldn't think of a way to invert these to exponentially-spaced numbers, besides, bounds can be negative.
Here's is what I have found so far :
Is there something like numpy.logspace in C++?
EXPLIST: Stata module to generate an exponentially-spaced list of numbers (No idea what this language is actually)
Generating a logarithmically spaced numbers
EDIT :
I should have given the problem a little more thinking before rushing to stackoverflow, here's what I actually did (inspired by this question) :
Given two bounds first and last, I wanted to generate a n-size array that starts with first and ends with last where each array's element is the exponential of some x.
This mathematical problem is a simple series U(i) that starts with U(0) = first and ends with U(n) = last with U(i) = first * q^i (for i in {0, 1, ..., n}) and q = pow(last / first, 1 / (n - 1)).
Here's a raw code :
#include <Eigen\Dense>
using namespace Eigen;
VectorXd expList(double first, double last, DenseIndex n)
{
VectorXd vector(n); // native C++ array or vector can be used of course
double m = (double) 1 / (n - 1);
double quotient = pow(last / first, m);
vector(0) = first;
for (DenseIndex i = 1; i < n; i++) // DenseIndex is just a typedef ptrdiff_t from the Eigen library
vector(i) = vector(i - 1) * quotient;
return vector;
}
This works for any same sign doubles first and last where first < last of course, but It can work for a negative first and positive last too with a little tweaking.
Example :
for first = 50 and last = 300 000 and a 100 elements array
I assume what you mean is a list of doubles (d1,...,dn) such that e^d(i+1)-e^di is constant?
In that case the following function should do what you want:
#include <vector>
#include <math.h>
#include <iostream>
std::vector<double> explist(double first, double last, double size)
{
if(first>last) std::swap(first,last);
double expfirst = exp(first);
double explast = exp(last);
double step = (explast-expfirst)/(size-1);
std::vector<double> out;
for(double x=expfirst; x<=explast; x+=step)
{
double a = log(x);
out.push_back(a);
}
return out;
}
int main()
{
std::vector<double> test = explist(0,1,6);
for(double d : test)
{
std::cout<<d<<" ";
}
std::cout<<std::endl;
for(double d : test)
{
std::cout<<exp(d)<<" ";
}
std::cout<<std::endl;
}
Output:
0 0.295395 0.523137 0.708513 0.86484 1
1 1.34366 1.68731 2.03097 2.37463 2.71828
At the moment this function only produces ascending lists (it just assumes that the smaller value is the left bound). There are several ways to make it work for descending lists as well (always assuming the leftmost argument to be the left bound). I just wanted to make the function as simple as possible and I think if you understand the function it will be easy for you to add that functionality.

Best program for Permutation nPr of large numbers

I am new to programming and was stuck at the permutation part. I have code which works for combination of large numbers which is stored in matrix but i am not able to find what should i change in that to get the result.
I tried the recursive method for permutations but could not achieve fast results.
This is the code which i got for combination what should be the change in condition which i should do here to get permutations?
void combination()
{
int i,j;
for(i=0;i<100;i++)
{
nCr[i][0]=1;
nCr[i][i]=1;
}
for(i=1;i<100;i++)
for(j=1;j<100;j++)
if (i!=j)
{
nCr[i][j] = (nCr[i-1][j] + nCr[i-1][j-1]);
}
}
A recurrence rule for permutations can be easily derived from the definition:
nPk = n*(n-1)*(n-2)* ... * (n-k+1) = n * (n-1)P(k-1)
Converted to code:
for(i=0;i<100;i++)
{
nPr[i][0]=1;
}
for(i=1;i<100;i++)
for(j=1;j<100;j++)
if (i!=j)
{
nPr[i][j] = i * nPr[i-1][j-1];
}
Note that the number of permutations grows fast and overflows the storage available for int: 13P11 for example is already out of range with signed 32bit integers.
well you can use the following pseudo-code for computing permutation and combination given that mod is always a very large prime number.
for permutation nPr
func permutation(r,n,mod):
q=factorial(n) // you should precompute them and saved in an array for a better execution time
r=(factorial(r))%mod
return (q*math.pow(r,mod-2))%mod
for combination nCr
func combination(r,n,mod):
q=factorial(n)
r=(factorial(r)*factorial(n-r))%mod
return (q*math.pow(r,mod-2))%mod
your should precompute factorials , for a decent execution time.
fact[100000]
fact[0]=fact[1]=1
func factorial_compute():
for x from 2 to 100000:
fact[x]=(x*fact[x-1])%mod
hence your factorial function will be
func factorial(x):
return(fact[x])
for reference on mathematics for this : http://mathworld.wolfram.com/ModularInverse.html
Actually, I know where the problem raised
At the point where we multiply , there is the actual problem ,when numbers get multiplied and get bigger and bigger.
this code is tested and is giving the correct result.
#include <bits/stdc++.h>
using namespace std;
#define mod 72057594037927936 // 2^56 (17 digits)
// #define mod 18446744073709551616 // 2^64 (20 digits) Not supported
long long int prod_uint64(long long int x, long long int y)
{
return x * y % mod;
}
int main()
{
long long int n=14, s = 1;
while (n != 1)
{
s = prod_uint64(s , n) ;
n--;
}
}

Optimizing my code for finding the factors of a given integer

Here is my code,but i'lld like to optimize it.I don't like the idea of it testing all the numbers before the square root of n,considering the fact that one could be faced with finding the factors of a large number. Your answers would be of great help. Thanks in advance.
unsigned int* factor(unsigned int n)
{
unsigned int tab[40];
int dim=0;
for(int i=2;i<=(int)sqrt(n);++i)
{
while(n%i==0)
{
tab[dim++]=i;
n/=i;
}
}
if(n>1)
tab[dim++]=n;
return tab;
}
Here's a suggestion on how to do this in 'proper' c++ (since you tagged as c++).
PS. Almost forgot to mention: I optimized the call to sqrt away :)
See it live on http://liveworkspace.org/code/6e2fcc2f7956fafbf637b54be2db014a
#include <vector>
#include <iostream>
#include <iterator>
#include <algorithm>
typedef unsigned int uint;
std::vector<uint> factor(uint n)
{
std::vector<uint> tab;
int dim=0;
for(unsigned long i=2;i*i <= n; ++i)
{
while(n%i==0)
{
tab.push_back(i);
n/=i;
}
}
if(n>1)
tab.push_back(n);
return tab;
}
void test(uint x)
{
auto v = factor(x);
std::cout << x << ":\t";
std::copy(v.begin(), v.end(), std::ostream_iterator<uint>(std::cout, ";"));
std::cout << std::endl;
}
int main(int argc, const char *argv[])
{
test(1);
test(2);
test(4);
test(43);
test(47);
test(9997);
}
Output
1:
2: 2;
4: 2;2;
43: 43;
47: 47;
9997: 13;769;
There's a simple change that will cut the run time somewhat: factor out all the 2's, then only check odd numbers.
If you use
... i*i <= n; ...
It may run much faster than i <= sqrt(n)
By the way, you should try to handle factors of negative n or at least be sure you never pass a neg number
I'm afraid you cannot. There is no known method in the planet can factorize large integers in polynomial time. However, there are some methods can help you slightly (not significantly) speed up your program. Search Wikipedia for more references. http://en.wikipedia.org/wiki/Integer_factorization
As seen from your solution , you find basically all prime numbers ( the condition while (n%i == 0)) works like that , especially for the case of large numbers , you could compute prime numbers beforehand, and keep checking only those. The prime number calculation could be done using Sieve of Eratosthenes method or some other efficient method.
unsigned int* factor(unsigned int n)
If unsigned int is the typical 32-bit type, the numbers are too small for any of the more advanced algorithms to pay off. The usual enhancements for the trial division are of course worthwhile.
If you're moving the division by 2 out of the loop, and divide only by odd numbers in the loop, as mentioned by Pete Becker, you're essentially halving the number of divisions needed to factor the input number, and thus speed up the function by a factor of very nearly 2.
If you carry that one step further and also eliminate the multiples of 3 from the divisors in the loop, you reduce the number of divisions and hence increase the speed by a factor close to 3 (on average; most numbers don't have any large prime factors, but are divisible by 2 or by 3, and for those the speedup is much smaller; but those numbers are quick to factor anyway. If you factor a longer range of numbers, the bulk of the time is spent factoring the few numbers with large prime divisors).
// if your compiler doesn't transform that to bit-operations, do it yourself
while(n % 2 == 0) {
tab[dim++] = 2;
n /= 2;
}
while(n % 3 == 0) {
tab[dim++] = 3;
n /= 3;
}
for(int d = 5, s = 2; d*d <= n; d += s, s = 6-s) {
while(n % d == 0) {
tab[dim++] = d;
n /= d;
}
}
If you're calling that function really often, it would be worthwhile to precompute the 6542 primes not exceeding 65535, store them in a static array, and divide only by the primes to eliminate all divisions that are a priori guaranteed to not find a divisor.
If unsigned int happens to be larger than 32 bits, then using one of the more advanced algorithms would be profitable. You should still begin with trial divisions to find the small prime factors (whether small should mean <= 1000, <= 10000, <= 100000 or perhaps <= 1000000 would need to be tested, my gut feeling says one of the smaller values would be better on average). If after the trial division phase the factorisation is not yet complete, check whether the remaining factor is prime using e.g. a deterministic (for the range in question) variant of the Miller-Rabin test. If it's not, search a factor using your favourite advanced algorithm. For 64 bit numbers, I'd recommend Pollard's rho algorithm or an elliptic curve factorisation. Pollard's rho algorithm is easier to implement and for numbers of that magnitude finds factors in comparable time, so that's my first recommendation.
Int is way to small to encounter any performance problems. I just tried to measure the time of your algorithm with boost but couldn't get any useful output (too fast). So you shouldn't worry about integers at all.
If you use i*i I was able to calculate 1.000.000 9-digit integers in 15.097 seconds. It's good to optimize an algorithm but instead of "wasting" time (depends on your situation) it's important to consider if a small improvement really is worth the effort. Sometimes you have to ask yourself if you rally need to be able to calculate 1.000.000 ints in 10 seconds or if 15 is fine as well.

Optimization algorithm with numbers

Given a list of numbers in increasing order and a certain sum, I'm trying to implement the optimal way of finding the sum. Using the biggest number first
A sample input would be:
3
1
2
5
11
where the first line the number of numbers we are using and the last line is the desired sum
the output would be:
1 x 1
2 x 5
which equals 11
I'm trying to interpret this https://www.classle.net/book/c-program-making-change-using-greedy-method using stdard input
Here is what i got so far
#include <iostream>
using namespace std;
int main()
{
int sol = 0; int array[]; int m[10];
while (!cin.eof())
{
cin >> array[i]; // add inputs to an array
i++;
}
x = array[0]; // number of
for (int i; i < x ; i++) {
while(sol<array[x+1]){
// try to check all multiplications of the largest number until its over the sum
// save the multiplication number into the m[] before it goes over the sum;
//then do the same with the second highest number and check if they can add up to sum
}
cout << m[//multiplication number] << "x" << array[//correct index]
return 0;
}
if(sol!=array[x+1])
{
cout<<endl<<"Not Possible!";
}
}
Finding it hard to find an efficient way of doing this in terms of trying all possible combinations starting with the biggest number? Any suggestions would be greatly helpful, since i know im clearly off
The problem is a variation of the subset sum problem, which is NP-Hard.
An NP-Hard problem is a problem that (among other things) - there is no known polynomial solution for it, thus the greedy approach of "getting the highest first" fails for it.
However, for this NP-Hard problem, there is a pseudo-polynomial solution using dynamic programming. The problem where you can chose each number more then once is called the con change problem.
This page contains explanation and possible solutions for the problem.

C++ program to calculate quotients of large factorials

How can I write a c++ program to calculate large factorials.
Example, if I want to calculate (100!) / (99!), we know the answer is 100, but if i calculate the factorials of the numerator and denominator individually, both the numbers are gigantically large.
expanding on Dirk's answer (which imo is the correct one):
#include "math.h"
#include "stdio.h"
int main(){
printf("%lf\n", (100.0/99.0) * exp(lgamma(100)-lgamma(99)) );
}
try it, it really does what you want even though it looks a little crazy if you are not familiar with it. Using a bigint library is going to be wildly inefficient. Taking exps of logs of gammas is super fast. This runs instantly.
The reason you need to multiply by 100/99 is that gamma is equivalent to n-1! not n!. So yeah, you could just do exp(lgamma(101)-lgamma(100)) instead. Also, gamma is defined for more than just integers.
You can use the Gamma function instead, see the Wikipedia page which also pointers to code.
Of course this particular expression should be optimized, but as for the title question, I like GMP because it offers a decent C++ interface, and is readily available.
#include <iostream>
#include <gmpxx.h>
mpz_class fact(unsigned int n)
{
mpz_class result(n);
while(n --> 1) result *= n;
return result;
}
int main()
{
mpz_class result = fact(100) / fact(99);
std::cout << result.get_str(10) << std::endl;
}
compiles on Linux with g++ -Wall -Wextra -o test test.cc -lgmpxx -lgmp
By the sounds of your comments, you also want to calculate expressions like 100!/(96!*4!).
Having "cancelled out the 96", leaving yourself with (97 * ... * 100)/4!, you can then keep the arithmetic within smaller bounds by taking as few numbers "from the top" as possible as you go. So, in this case:
i = 96
j = 4
result = i
while (i <= 100) or (j > 1)
if (j > 1) and (result % j == 0)
result /= j
--j
else
result *= i
++i
You can of course be cleverer than that in the same vein.
This just delays the inevitable, though: eventually you reach the limits of your fixed-size type. Factorials explode so quickly that for heavy-duty use you're going to need multiple-precision.
Here's an example of how to do so:
http://www.daniweb.com/code/snippet216490.html
The approach they take is to store the big #s as a character array of digits.
Also see this SO question: Calculate the factorial of an arbitrarily large number, showing all the digits
You can use a big integer library like gmp which can handle arbitrarily large integers.
The only optimization that can be made here (considering that in m!/n! m is larger than n) means crossing out everything you can before using multiplication.
If m is less than n we would have to swap the elements first, then calculate the factorial and then make something like 1 / result. Note that the result in this case would be double and you should handle it as double.
Here is the code.
if (m == n) return 1;
// If 'm' is less than 'n' we would have
// to calculate the denominator first and then
// make one division operation
bool need_swap = (m < n);
if (need_swap) std::swap(m, n);
// #note You could also use some BIG integer implementation,
// if your factorial would still be big after crossing some values
// Store the result here
int result = 1;
for (int i = m; i > n; --i) {
result *= i;
}
// Here comes the division if needed
// After that, we swap the elements back
if (need_swap) {
// Note the double here
// If m is always > n then these lines are not needed
double fractional_result = (double)1 / result;
std::swap(m, n);
}
Also to mention (if you need some big int implementation and want to do it yourself) - the best approach that is not so hard to implement is to treat your int as a sequence of blocks and the best is to split your int to series, that contain 4 digits each.
Example: 1234 | 4567 | 2323 | 2345 | .... Then you'll have to implement every basic operation that you need (sum, mult, maybe pow, division is actually a tough one).
To solve x!/y! for x > y:
int product = 1;
for(int i=0; i < x - y; i ++)
{
product *= x-i;
}
If y > x switch the variables and take the reciprocal of your solution.
I asked a similar question, and got some pointers to some libraries:
How can I calculate a factorial in C# using a library call?
It depends on whether or not you need all the digits, or just something close. If you just want something close, Stirling's Approximation is a good place to start.