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"
}

No comments:

Post a Comment