Tuesday, June 22, 2010

Halloween treats

problem code: HALLOW

Every year there is the same problem at Halloween: Each neighbor is only willing to give a certain total number of sweets on that day, no matter how many children call on him, so it may happen that a child will get nothing if it is too late. To avoid conflicts, the children have decided they will put all sweets together and then divide them evenly among themselves. From last year's experience of Halloween they know how many sweets they get from each neighbor. Since they care more about justice than about the number of sweets they get, they want to select a subset of the neighbors to visit, so that in sharing every child receives the same number of sweets. They will not be satisfied if they have any sweets left which cannot be divided.

Your job is to help the children and present a solution.
Given integers c and n (1 ≤ c ≤ n ≤ 100000), the number of children and the number of neighbors, respectively, n integers a1 , ... , an (1 ≤ ai ≤ 100000 ), where ai represents the number of sweets the children get if they visit neighbor i.
output one line with the indexes of the neighbors the children should select (here, index i corresponds to neighbor i who gives a total number of ai sweets). If there is no solution where each child gets at least one sweet, print "no sweets" instead.
To solve this problem you have to know the following:
1- If we have 3 persons, they can't have different genders
2- There must be at least two persons who have the same hair count in their head ?
3- If we select 101 integer from 0 to 200 we must have at least 1 even integer selected ?

Also if there is N pigeon and M pigeonholes where N < style="font-weight: bold;">pigeonhole principle)

I think now you are saying what trivial information you are telling these all are trivial things and we know them !! :D

But let me continue with this theorem:

"If n objects are put into n boxes, then at least 1 box contains two or more objects" now you know the theorem "if you didn't know it from before"

Now back to the solution of the problem:
let me state the givens again:
Number of children : c
Number of neighbors: n
c <= n
Sweets that every neighbor can give A0,A1,....,An-1.

we want to pick some of As so we have the sum mod n equals zero
From the pigeonhole principle we know that there is always a solution which contain some consecutive elements (WHY ?? )

lets make cumulative array that contain in index i the sum of all elements from index 0 to index i
i claim that if we get the mod of c for each element on the array, either you will find mod zero ( so here is the solution from the start to this element) or one of the mods at least will appear more than one time "pigeonhole principle" so between these any two appearances of this mod is the solution :)

The following function returns two indexes that contain the solution between them

code :


pair<int,int> getsol(int neighbors,int children, int* visited,
int* give)
{
// visited: where did i visit this MOD before
// give: array contain in index i that amount of treats
// that neighbor i will give
memset(visited,-1,sizeof(int)*(children+2));
// no Mods visited till now

v[0]=0; // mod zero visited before getting any treat
for(int i = 0,sum=0 ; i < neighbors ; i ++)
{
sum+=give[i];
sum%=children;
if(visited[sum]==-1)
visited[sum]=i+1; // visit this mod if not visited
else
return make_pair(visited[sum],i); // if this mod visited before
// so the solution is between visited[sum] and i inclusive (0 based)
}
return make_pair(-1,-1);
// no solution "it will never happen in this problem"
}

Sunday, June 6, 2010

Permutation Index

Problem:
While i was developing a parallel application i faced a problem, this problem says "given set of letters, can you tell me the permutation number X if all permutation are sorted in lexicographical order ?"
example:
letters {a, b, c}
Permutations: abc, acb, bac, bca, cab,cba
what i want given number N generate the permutation which index is N (eg. 3-> bca)

The normal solution for this problem is using the function next_permutation N times till finding the solution - and this is not an efficient solution because as you know the number of permutations is Factorial the length of the letters set ..

At this point: we have to search for a method that we can use to generate the permutation directly without passing on all other permutations

Solution :
As we mentioned in the problem you know that Number of Permutations with length X
is factorial X
okay lets use the given example:
letters {a, b, c}
perumtations are 3! = 6 Why ??
because the first letter can have 3 choices the second can have 2 (we removed the letter we choose in the first) and the third have only 1 choice so 3*2*1 = 6
from that we can say that there is 6 permutations it can start with 3 letters each letter can be followed by (2*1) permutations
abc, acb (2 permutations starting with a)
bac, bca (2 permutations starting with b)
cab, cba (2 permutations starting with c)

For any string of length N there exist N! permutation - also there exist (N-1)! Permutations starts with each letter(why ?)
Because when we use the first letter we can use it again so we have N-1 letter we want to make different permutations for it so we have (N-1)! permutations for them
from that we can think of a very simple method
i'll illustrate this method by example:
In {a,b,c},what is the permutation with index 3 ?

We know that (0,1 start with a) - (2,3 start with b) - (4,5 start with c)
so the string till now is "b"
Then we remove b from the choices and so we have only 2 remaining letters (a,c)
now the remaining index is 1

Again get index 1 in permutations (a,c)
using the same method i get that this permutation starts with c ( as there is 2! permutations 1 starting with a and 1 starting with c)
now the string till now is "bc"

Again lets get the reminder which is 0
having letter (a) i want to get the permutation number 0 : it's a
so the string is "bca"

From that we know that i can get the first character by dividing by (N-1)!
then remove this character from the set and adding it to the string
then getting the new index (reminder) by getting the mod with (N-1)!
and then do that again till generating the whole string

Code:

string getNthPermutation(long long index,string st)
{
// st is sorted string contain the letters
if(st=="")return"";
int len = st.size();
long long fact = factorial(len-1);
long long frst = index/fact;
char frstChar = st[frst];
long long newIndex = index%fact;
st.erase(st.begin()+frst);
return frstChar + getNthPermutation(newIndex,st);
}