Enumerating a set of permutations based on a condition - c++

I've been able to solve the following problem using std::next_permutation (c++) etc,
but I'm now thinking about it in a more general and would very much like to form an
expression as this type of problem seems to lend itself - though I'm not having any luck as of yet.
Here is the question:
Given a running race with N contestants, what is the probability that exactly M contestants will finish in a position that is the same as the number on their shirt.
Where M <= N.
What I've done so far:
There will be N! ways the race can end,
I've tried fiddling with a small variant of the problem consisting of either 3 or 4 contestants with
the required number of people meeting the condition as being 2. in both cases for 2 people finishing in the particular order the probability is 1/2
I'd like to know if there's already some kind of expression that handles all the cases?
Some code:
#include <cstdio>
#include <algorithm>
#include <vector>
int main(int argc, char* argv[]) {
if (argc != 3) return 1;
int n = atoi(argv[1]);
int m = atoi(argv[2]);
if (m > n) return 1;
std::vector<int> lst(n);
for (int i = 0; i < n; ++i) lst[i] = i;
unsigned int total = 0;
unsigned int perm_count = 0;
do {
int cnt = 0;
for (int i = 0; i < n; ++i) if (lst[i] == i) ++cnt;
if (cnt == m)
++total;
++perm_count;
}
while (std::next_permutation(lst.begin(),lst.end()));
printf("Probability of (%d,%d) = %8.7f\n",n,m,(1.0 * total / perm_count));
return 0;
}
Update: The expression is called a Partial Derangement:
http://mathworld.wolfram.com/PartialDerangement.html
Note1: The formula is correct, if one assumes that the fully ordered permutation does not count.
Note2: I've changed the question slightly to make it more clear, hence also changed to code - this should reconsile with comments made by ShreevatsaR.

The number of permutations of a set with n elements containing m fixed points is
D(n,m) = \frac{n!}{m!}\sum_{k=0}^{n-m}\frac{(-1)^k}{k!} http://bit.ly/aaKqUq
(see http://en.wikipedia.org/wiki/Random_permutation_statistics#Number_of_permutations_that_are_derangements)
Therefore, the probability is D(n,m)/n!, i.e.
d(n,m) = \frac{1}{m!}\sum_{k=0}^{n-m}\frac{(-1)^k}{k!} http://bit.ly/aVqSkA

There are two definitions you need to solve this in closed form:
The number of ways to permute N people is N! (N factorial), or N * N-1 * N-2 * ... * 1. These are called permutations.
The number of ways to choose M people from N is called (N choose M), and it equals N! / (M! (N-M)!) - these are called combinations. (If this is new to you, do a Google search for "permutations and combinations".)
I'm working on a closed-form solution...

Related

Finding Xth term of a series

I have a simple problem.
I am having an array A[] of N numbers. I have to perform this operarion:
for(i = 2; i<=N; i++)
A[i] = A[i] + A[i-1]
to the array A[] k times. And after performing this operation k times, I have to output the Xth index element.
Doing it with brute force, will lead to TLE.
I was searching for some pattern, but, I came to a solution which is not perfect as it needs to be.
Can you please help me, to find some more efficient solution to this problem.
I have an example, to clear the question.
Let's say array A is [1,2,3] and I need to perform the above operation 3 times then:
Array after 1st turn: A=[1,3,6]
Array after 2nd turn: A=[1,4,10]
Array after 3rd turn: A=[1,5,15]
So, if I am required to find the 2nd element of the array now, then it would be 5.
I you look to the Pascal's triangle (as #MBo say) you may notice that after k times the number of times each number get added in the final result is equal to a square in the triangle following the diagonals. Let see an example here:
This image correspond to iterate four times for the first three elements. So, as you can see if we have as input k equal to the number of times and n equal to the index of the element to return, all we have to do is multiply each of the numbers in the diagonal filled in blue until the red line (the image configuration correspond to k = 4 and n = 2).
After that, we have this formula:
Now, to improve the way we calculate the formula show above, we can use dynamic programming and calculate the factorial function from 0 ... k+n (note that the bigger number in the sequence is k-1+n). With this we can access to factorial(n) in a constant time. Also if we expand the combinatoric factor inside the summation we notice that the factor (k - 1 + i - i)! = (k - 1)! so, we can put this outside the summation.
Here is the code:
#include "stdafx.h"
#include "iostream"
using namespace std;
int findingXth(int a[], int n, int k, int factorial[]){
if (k == 0)
return a[n];
int result = 0;
for (int i = 0; i <= n; ++i)
{
int up = k - 1 + i;
result += (factorial[up] / factorial[i]) * a[n - i];
}
return result / factorial[k - 1];
}
int main(int argc, _TCHAR* argv[])
{
int a[3] = { 1, 2, 3 };
int n = 2;
int k = 3;
int factorial[100000]; // probably the expecification of the problem has some upper bounds for n and k (the length of the factorial array can be set to n+k+1);
factorial[0] = 1;
for (int i = 1; i < n + k; i++)
{
factorial[i] = factorial[i - 1] * i;
}
int result = findingXth(a, n, k, factorial);
std::cout << result;
return 0;
}

Count unique subsets of size k with some S [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
Team 7 faces a horrible foe. He can only be defeated with a special
quadruple combination attack of strength ( 1 <=S <= 10^9 ).
Naruto, Sasuke, Sakura and Kakashi must attack simultaneously to
perform the combo. Each of them can choose from N ( 1 <= N <=1000 ) attacks, having strengths si each ( 0 <= i < N, 1 <= si <=10^9). The strengths of individual attacks add up to form the
strength of the combo.
Is there a valid combination that they can use? Note that the same
attacks are available to all of them.
You are required to write a function which takes input as follows – An
integer N as number of attacks, an integer vector s[] as the
strengths of N attacks and an integer S as the required strength
of the combo. Set the output variable to the number of distinct valid
combos.
Two combinations are different if they differ in strength of at least
one attack used.
Input: 1 {1} 4
Output: 1 ===>{1,1,1,1}
Input: 2 {1,2} 5
Output: 1 ===> {1,1,1,2}
Below is my code its only passes 3 test cases out of 10. I don't know the test cases as it was some online code submission.
My Algorithm:
1) Create a hash with indexes as sum of pairs from input array and value as individual elements contributing to sum
2) Iterate over the hash and look if for i in hash there is k-i
3) Count above indexes and return count/2 as we are counting for both H(i) and H(k-i)
Please review the code and tell me what scenarios you think code will not produce right o/p.
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<vector>
#include<map>
#include<set>
const int noOfPalyers = 4;
int validCombo(int input1,int input2[],int input3)
{
//Write code here
int count = 0;
std::vector<int> vec;
int size =input1*noOfPalyers;
for(int i = 0; i < input1; i++)
{
for(int j = 0; j < noOfPalyers;j++)
{
vec.push_back(input2[i]);
}
}
std::vector< std::set< std::pair<int, int> > > vecHash;
//vecHash.reserve(size*size);
for(int i =0; i < (size*size); i++)
{
vecHash.push_back(std::set< std::pair<int, int> >());
}
for(int i =0; i < size; i++)
{
for(int j =1; j < size; j++)
{
int key = vec[i] + vec[j];
if(vec[i]<= vec[j])
vecHash[key].insert(std::make_pair(vec[i], vec[j]));
else
vecHash[key].insert(std::make_pair(vec[j], vec[i]));
}
}
for(int i = 0; i < input3; i++)
{
if(vecHash[i].size() > 0 && i < input3)
{
if(vecHash[input3-i].size() > 0)
{
std::set< std::pair<int, int> >::iterator iter, iter2;
for(iter=vecHash[i].begin(); iter!=vecHash[i].end();++iter)
{
for(iter2=vecHash[input3-i].begin(); iter2!=vecHash[input3-i].end();++iter2)
{
std::cout<<(*iter).first<<","<< (*iter).second<<",";
std::cout<<(*iter2).first<<","<< (*iter2).second;
std::cout<<"\n";
count++;
}
}
}
}
}
return (count ==1 ? count: count/2);
}
int main()
{
int i = 3;
int arr[] = {1,2,3};
int j = 7;
int arr1[] ={1};
std::cout <<"o/p == " << validCombo(i, arr, j)<< "\n";
std::cout <<"o/p == " << validCombo(1, arr1, 4);
//getch();
return 0;
}
UPD. My God, now I've understood your comment :) and see that you tried to solve it the same way I wrote. Anyway, I hope you'll find some pieces of my explanation useful. First of all, you don't use hash functions (I know identity function is a hash func, but not the good one in our case). Also I didn't understand your count logic... I think you need to read Two combinations are different if they differ in strength of at least one attack used. part again and check your count logic.
There're just my first thoughts. Hope it could be helpful.
==================================
You know, this problem is about having particular sum of 4 numbers from the set. Let's imagine we have just 2 heroes (so 2 terms in our sum):
a + b = S,
where a, b are attack's strengths from set of N numbers (let's name it T). The number of different a + b sums is N^2. Simple calculating all of these sums and then searching those ones equal to S doesn't give us good solution. This problem can be solved with better complexity.
If we could find a fast function such that:
F(a) = F(S - b)
we would precalculate all F(S - b), then looped over all a's and found which ones satisfy equality above. You mentioned hash. Hash functions can do this. We need such hash func to map all numbers from set T to range [0, N]. Because we just have no more than N different a's.
But we have a little problem here:
F(a) = F(S - b) just means a can be equal to S - b. Fortunately, it's not a big problem,
because the main power is: F(a) != F(S - b) means a != S - b.
Ok, as you see we have algorithm to solve a + b = S problem with amortized O(N) complexity. Sounds good and promising, right? :)
==================================
Now come back to your problem:
a + b + c + d = S
My idea to precalculate all f(a + b) with O(N^2) and store them like this (warning! just pseudocode):
vector<int> hash = new vector<int>(with size N)
foreach (a in T)
foreach (b in T)
{
int x = OurHashFunc(a + b); // a + b <= 2 * 10^9 so it never overflows int
if (hash[x] == null)
hash[x] = new vector<pair<int,int>>
hash[x].push_back(new pair<int, int>(a, b));
}
We keep pairs (a,b) to be able to restore terms of initial sum. Then if our OurHashFunc is additive then transform our initial problem like this:
a + b + c + d = S // apply hash func =>
f(a + b) + f(c + d) = f(S) // rename =>
x + y = Z // wow, I bet I've already seen this equation ;)
Now 4-terms sum problem had reduced to 2-terms sum problem with an O(N^2) overhead.
I think this reduction can be continued: 2^k-terms sum problem should have avg O(N^k) solution.

C++ program to find the largest palindrome which is product of two two digit numbers [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I have seen this, but this is not what I am looking for.
The problem is same that is to find the largest palindrome which is the product of two three digit numbers.
Since my program was not working so I made a little change, instead of finding the largest palindrome which is the product of two three digit numbers I have written the program to find the largest palindrome which is the product of two two digit numbers.
Kindly see the program:
#include <iostream>
using namespace std;
int main() {
int i, j, n, s, m, w;
for (i = 99; i > 9; i--) {
for (j = 99; j > 9; j--)
n = i * j;
s = n;
while (n != 0) {
w = 0;
m = n % 10;
w = w * 10 + m;
n = n / 10;
}
if (s == w)
cout << s << endl;
break;
}
return 0;
}
The problem with this program is that it is neither showing any error nor giving any result.
So kindly help me to find the problem in my program.
Right now you are missing the curly braces for the j-loop. The current code is doing 99! * i.
Then you would have to focus on storing the largest palindrome value instead of just printing all those values to the screen (this is considering your implementation, it is not the most efficient one by any means).
Some modified version of your code:
#include <iostream>
using namespace std;
int main() {
int max_product = 0;
for (int i = 99; i > 9; i--) {
for (int j = i; j > 9; j--) {
int product = i * j;
if (product < max_product)
break;
int number = product;
int reverse = 0;
while (number != 0) {
reverse = reverse * 10 + number % 10;
number /= 10;
}
if (product == reverse && product > max_product) {
max_product = product;
}
}
}
cout << "Solution: " << max_product << endl;
return 0;
}
You have various problems:
Need one more pair of {, }. After the for-loop of j. The only instruction the for-loop of j is executing is: n = i * j; with the braces the rest of the instruction (testing if it's a palindrome) are out of the loop.
the variable w the reverse of the number to test for palindrome is reset his value to 0 in every execution of while (n != 0) loop resulting in incorrect reverse value (and never find the palindrome).
The max palindrome product of 2 two digits number don't have to be the first one found with this 2 for-loop, eg: suppose that there is 2 valid solutions i = 98, j = 2 and i = 70, j = 65 in this case i*j would be in first solution = 196 in the second = 4550 and when you found the first you could not stop the search. In your code using the break don't do what I think you are waiting for (stop the search), only stop the search with the actual i value.
Some notes about the modified code:
The two for-loop don't need to be from 99..9, in this case you are testing a lot of product two times (eg: 98*99, are testing when i == 98 and j == 99 and i == 99 and j == 98), you could restrict j to be always less or equal to i.
Using max_product to maintain the maximum palindrome product found. And use that info in the inner loop (if (product < max_product)) for early exit when no better solution could be found.

Find which two values in an array maximize a given expression?

I met a very simple interview question, but my solution is incorrect. Any helps on this? 1)any bugs in my solution? 2)any good idea for time complexity O(n)?
Question:
Given an int array A[], define X=A[i]+A[j]+(j-i), j>=i. Find max value of X?
My solution is:
int solution(vector<int> &A){
if(A.empty())
return -1;
long long max_dis=-2000000000, cur_dis;
int size = A.size();
for(int i=0;i<size;i++){
for(int j=i;j<size;j++){
cur_dis=A[j]+A[i]+(j-i);
if(cur_dis > max_dis)
max_dis=cur_dis;
}
}
return max_dis;
}
The crucial insight is that it can be done in O(n) only if you track where potentially useful values are even before you're certain they'll prove usable.
Start with best_i = best_j = max_i = 0. The first two track the i and j values to use in the solution. The next one will record the index with the highest contributing factor for i, i.e. where A[i] - i is highest.
Let's call the value of X for some values of i and j "Xi,j", and start by recording our best solution so far ala Xbest = X0,0
Increment n along the array...
whenever the value at [n] gives a better "i" contribution for A[i] - i than max_i, update max_i.
whenever using n as the "j" index yields Xmax_i,n greater than Xbest, best_i = max_i, best_j = n.
Discussion - why/how it works
j_random_hacker's comment suggests I sketch a proof, but honestly I've no idea where to start. I'll try to explain as best I can - if someone else has a better explanation please chip in....
Restating the problem: greatest Xi,j where j >= i. Given we can set an initial Xbest of X0,0, the problem is knowing when to update it and to what. As we contemplate successive indices in the array as potential values for j, we want to generate Xi,j=n for some i (discussed next) to compare with Xbest. But, what i value to use? Well, given any index from 0 to n is <= j, the j >= i constraint isn't relevant if we pick the best i value from the indices we've already visited. We work out the best i value by separating the i-related contribution to X from the j-related contribution - A[i] - i - so in preparation for considering whether we've a new best solution with j=n we must maintain the best_i variable too as we go.
A way to approach the problem
For whatever it's worth - when I was groping around for a solution, I wrote down on paper some imaginary i and j contributions that I could see covered the interesting cases... where Ci and Cj are the contributions related to n's use as i and j respectively, something like
n 0 1 2 3 4
Ci 4 2 8 3 1
Cj 12 4 3 5 9
You'll notice I didn't bother picking values where Ci could be A[i] - i while Cj was A[j] + j... I could see the emerging solution should work for any formulas, and that would have just made it harder to capture the interesting cases. So - what's the interesting case? When n = 2 the Ci value is higher than anything we've seen in earlier elements, but given only knowledge of those earlier elements we can't yet see a way to use it. That scenario is the single "great" complication of the problem. What's needed is a Cj value of at least 9 so Xbest is improved, which happens to come along when n = 4. If we'd found an even better Ci at [3] then we'd of course want to use that. best_i tracks where that waiting-on-a-good-enough-Cj value index is.
Longer version of my comment: what about iterating the array from both ends, trying to find the highest number, while decreasing it by the distance from the appripriate end. Would that find the correct indexes (and thus the correct X)?
#include <vector>
#include <algorithm>
#include <iostream>
#include <random>
#include <climits>
long long brutal(const std::vector<int>& a) {
long long x = LLONG_MIN;
for(int i=0; i < a.size(); i++)
for(int j=i; j < a.size(); j++)
x = std::max(x, (long long)a[i] + a[j] + j-i);
return x;
}
long long smart(const std::vector<int>& a) {
if(a.size() == 0) return LLONG_MIN;
long long x = LLONG_MIN, y = x;
for(int i = 0; i < a.size(); i++)
x = std::max(x, (long long)a[i]-i);
for(int j = 0; j < a.size(); j++)
y = std::max(y, (long long)a[j]+j);
return x + y;
}
int main() {
std::random_device rd;
std::uniform_int_distribution<int> rlen(0, 1000);
std::uniform_int_distribution<int> rnum(INT_MIN,INT_MAX);
std::vector<int> v;
for(int loop = 0; loop < 10000; loop++) {
v.resize(rlen(rd));
for(int i = 0; i < v.size(); i++)
v[i] = rnum(rd);
if(brutal(v) != smart(v)) {
std::cout << "bad" << std::endl;
return -1;
}
}
std::cout << "good" << std::endl;
}
I'll write in pseudo code because I don't have much time, but this should be the most performing way using recursion
compare(array, left, right)
val = array[left] + array[right] + (right - left);
if (right - left) > 1
val1 = compare(array, left, right-1);
val2 = compare(array, left+1, right);
val = Max(Max(val1,val2),val);
end if
return val
and than you call simply
compare(array,0,array.length);
I think I found a incredibly faster solution but you need to check it:
you need to rewrite your array as follow
Array[i] = array[i] + (MOD((array.lenght / 2) - i));
Then you just find the 2 highest value of the array and sum them, that should be your solution, almost O(n)
wait maybe I'm missing something... I have to check.
Ok you get the 2 highest value from this New Array, and save the positions i, and j. Then you need to calculate from the original array your result.
------------ EDIT
This should be an implementation of the method suggested by Tony D (in c#) that I tested.
int best_i, best_j, max_i, currentMax;
best_i = 0;
best_j = 0;
max_i = 0;
currentMax = 0;
for (int n = 0; n < array.Count; n++)
{
if (array[n] - n > array[max_i] - max_i) max_i = n;
if (array[n] + array[max_i] - (n - max_i) > currentMax)
{
best_i = max_i;
best_j = n;
currentMax = array[n] + array[max_i] - (n - max_i);
}
}
return currentMax;
Question:
Given an int array A[], define X=A[i]+A[j]+(j-i), j>=i. Find max value of X?
Answer O(n):
lets rewrite the formula: X = A[i]-i + A[j]+j
we can track the highest A[i]-i we got and the highest A[j]+j we got. We loop over the array once and update both of our max values. After looping once we return the sum of A[i]-i + A[j]+j, which equals X.
We absolutely don't care about the j>=i constraint, because it is always true when we maximize both A[i]-i and A[j]+j
Code:
int solution(vector<int> &A){
if(A.empty()) return -1;
long long max_Ai_part =-2000000000;
long long max_Aj_part =-2000000000;
int size = A.size();
for(int i=0;i<size;i++){
if(max_Ai_part < A[i] - i)
max_Ai_part = A[i] - i;
if(max_Aj_part < A[j] + j)
max_Ai_part = A[j] - j;
}
return max_Ai_part + max_Aj_part;
}
Bonus:
most people get confused with the j>=i constraint. If you have a feeling for numbers, you should be able to see that i should tend to be lower than j.
Assume we have our formula, it is maximized and i > j. (this is impossible, but lets check it out)
we define x1 := j-i and x2 = i-j
A[i]+A[j]+j-i = A[i]+A[j] + x1, x1 < 0
we could then swap i with j and end up with this:
A[j]+A[i]+i-j = A[i]+A[j] + x2, x2 > 0
it is basically the same formula, but now because i > j the second formula will be greater than the first. In other words we could increase the maximum by swapping i and j which can't be true if we already had the maximum.
If we ever find a maximum, i cannot be greater than j.

Given number N eliminate K digits to get maximum possible number

As the title says, the task is:
Given number N eliminate K digits to get maximum possible number. The digits must remain at their positions.
Example: n = 12345, k = 3, max = 45 (first three digits eliminated and digits mustn't be moved to another position).
Any idea how to solve this?
(It's not homework, I am preparing for an algorithm contest and solve problems on online judges.)
1 <= N <= 2^60, 1 <= K <= 20.
Edit: Here is my solution. It's working :)
#include <iostream>
#include <string>
#include <queue>
#include <vector>
#include <iomanip>
#include <algorithm>
#include <cmath>
using namespace std;
int main()
{
string n;
int k;
cin >> n >> k;
int b = n.size() - k - 1;
int c = n.size() - b;
int ind = 0;
vector<char> res;
char max = n.at(0);
for (int i=0; i<n.size() && res.size() < n.size()-k; i++) {
max = n.at(i);
ind = i;
for (int j=i; j<i+c; j++) {
if (n.at(j) > max) {
max = n.at(j);
ind = j;
}
}
b--;
c = n.size() - 1 - ind - b;
res.push_back(max);
i = ind;
}
for (int i=0; i<res.size(); i++)
cout << res.at(i);
cout << endl;
return 0;
}
Brute force should be fast enough for your restrictions: n will have max 19 digits. Generate all positive integers with numDigits(n) bits. If k bits are set, then remove the digits at positions corresponding to the set bits. Compare the result with the global optimum and update if needed.
Complexity: O(2^log n * log n). While this may seem like a lot and the same thing as O(n) asymptotically, it's going to be much faster in practice, because the logarithm in O(2^log n * log n) is a base 10 logarithm, which will give a much smaller value (1 + log base 10 of n gives you the number of digits of n).
You can avoid the log n factor by generating combinations of n taken n - k at a time and building the number made up of the chosen n - k positions as you generate each combination (pass it as a parameter). This basically means you solve the similar problem: given n, pick n - k digits in order such that the resulting number is maximum).
Note: there is a method to solve this that does not involve brute force, but I wanted to show the OP this solution as well, since he asked how it could be brute forced in the comments. For the optimal method, investigate what would happen if we built our number digit by digit from left to right, and, for each digit d, we would remove all currently selected digits that are smaller than it. When can we remove them and when can't we?
In the leftmost k+1 digits, find the largest one (let us say it is located at ith location. In case there are multiple occurrences choose the leftmost one). Keep it. Repeat the algorithm for k_new = k-i+1, newNumber = i+1 to n digits of the original number.
Eg. k=5 and number = 7454982641
First k+1 digits: 745498
Best number is 9 and it is located at location i=5.
new_k=1, new number = 82641
First k+1 digits: 82
Best number is 8 and it is located at i=1.
new_k=1, new number = 2641
First k+1 digits: 26
Best number is 6 and it is located at i=2
new_k=0, new number = 41
Answer: 98641
Complexity is O(n) where n is the size of the input number.
Edit: As iVlad mentioned, in the worst case complexity can be quadratic. You can avoid that by maintaining a heap of size at most k+1 which will increase complexity to O(nlogk).
Following may help:
void removeNumb(std::vector<int>& v, int k)
{
if (k == 0) { return; }
if (k >= v.size()) {
v.clear();
return;
}
for (int i = 0; i != v.size() - 1; )
{
if (v[i] < v[i + 1]) {
v.erase(v.begin() + i);
if (--k == 0) { return; }
i = std::max(i - 1, 0);
} else {
++i;
}
}
v.resize(v.size() - k);
}