Can you help me with these two problems from italian olympiad?
- - -
In the sample above, an optimal sequence is:
11 -4 52 -7 -2 -20
11 -4 52 -7 -22
11 -4 52 -29
11 -4 23
7 23
30
The values of Y are: -22, -29, 23, 7, 30. The maximum |Y| is 30. We can't do better as the sum of elements in S is 30.
Another sample:
7 -1 -8
6 -8
-2
The values of Y are: 6, -2. The answer is 6.
The time limit is 3s.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
In a strange planet the inhabitants speak a strange language, the alphabet is formed by binary digits. The dictionary is formed only by words not containing a sequence S of length M. Each word has length N (N ≥ M).
For example, if S = 01, then the binary words of lenght N = 4 not containing S are: 0000, 1000, 1100, 1110, 1111. If S = 11, the words are: 0000, 1000, 0100, 0010, 1010, 0001, 1001, 0101.
We know that 1 ≤ N, M ≤ 1000. Ouput the number of words in the dictionary, modulo 2011.
How the input is formed: first line (M, N), second line: sequence S.
Time limit: 1s.
Sample input:
2 4 01
Sample output:
5Sample input:
2 1511Sample output:
1597- - - - - - - - - - - -
Isn't the segment (length >= 2) with maximum sum of it's elements an answer to first task? It can be found in O(N).
Let s[i] be a_1 + a_2 + ... + a_i. For each i let's find j: j < i and s[j] is the least one among all possible j. The answer is max(s[i] - s[j]) among all i. It can be done with two pointers, i and j. On each iteration we should increase i, and if s[i] < s[j] then j = i. You should also handle that i-j+1 >= 2 (because len >= 2), but that's not so hard.
Thanks, I didn't know the correct word for subarray in English. In Russian it sounds like subsegment.
I think that it's exactly the same problem. The only difference is that we should maximize |Y| instead of Y. Really, let our array look like [L] a_k a_k+1 [R], where [L] and [R] are subarrays and a_k and a_k+1 is a result of collapsing of some subarray [M] (a_k + a_k+1 = sum([M])). Any operations within [L] and [R] do not affect on a_k and a_k+1, so a_k + a_k+1 is maximum if and only if [M] is a maximum subarray.
Oops. This way it seems that we can only sum two numbers adjacent not only to each other but to the side of an array. So an answer is maximum prefix/suffix. It also seems to be too easy.
Maybe I misunderstood something in statement, maybe you reprinted something wrong... Anyway, may I see an original statement (if there is one in English)?
11 -4 52 -7 -2 -20
11 -4 52 -7 -22
11 48 -7 -22
11 41 -22
11 19
30
for second problem you need to construct "error fucntion" (see KMP algorithm), then use DP(len, vertex).
vertex means the length of maximum suffix of already constructed string, which also is a suffix of string s.
let's s = "1010111" and already constructed string is 111111101011, then suffix 101011 (111111[101011] ) is also a prefix of s ( [101011]1 ) so we in DP state (12, 6) now we can to add 0 to our string and go into DP state (13, 2) or to add 1 and go into DP state (13, 7) (when we reach state where vertex = s.length(), it means that constructed string contain s as a substring.
Let f(a,b) = min power by converting elements in range from a to b into a single element.
Then f(a,b) = max( abs(sum(a,b)), min(f(a,i), f(i+1,b)) ) for i from a+1 to b-1
For Q2, there is an N^2 dp
Firstly, you precompute the longest common prefix between any two suffixes of the given string. You can do this by using a suffix array, but that would be an overkill. Using an N^2 precomputation would be good enough.
There f(x,a) = number of ways to construct valid strings of length x such that the last a characters is a suffix of S, and a is as large as possible.
Then f(x,a) = f(x+1,a+1) (this is the case where you increase the length of the suffix)
+ f(x+1,b) (this is the case where you have changed the length of the new suffix)
note that f(x,M) = 0
Yes, you should precompute such that you can retrieve sum(a,b) in constant time.
What I gave is a recursive solution. If you want an iterative solution, it is probably something like this:
for(int x=1;x<n;++x)
for(int a=1;a<=n;++a)
for(int k=1;k<=x;++k)
dp[a][a+x] = min(abs(sum(a,b)), min(dp[a][a+k],dp[a+k+1][a+x]));
If you want a recursive solution, just use the recursion I have given.
Let S[] be the boolean array representing the forbidden subsequence.
We proceed with dynamic programming: let c[i][j] be the number of words of length i starting with j (which can be 0 or 1) which don't contain S. For i up to M-1 their value is trivial (2^(i-1)).
For i >= M I think their value might be computed this way:
The idea behind this is:
Consider the complete binary tree of height N where each path from the root to a leaf represent a different binary string of length N. Consider a node at height i. If that node has a value of S[0] then there is a path (of length M) starting on that node which describes the sequence S. All paths from the root to a leaf which contains that path in its entirety cannot represent a word in the dictionary (they contain the forbidden subsequence!). Thus, the only allowed words starting on that node are the ones contained in the subtrees which don't belong to that path.
Let's consider this example:
http://imageshack.us/photo/my-images/249/path2985983195.png/
S = [1,0,1] and the corresponding nodes are marked in red. The set of allowed paths in the whole tree is the union of the ones in the subtrees rooted in the green nodes. So we recurse on them (actually we use dynamic programming). By recursing on the first node we get 7 paths (there's another 101 in that subtree we have to exclude), on the second we get 3, on the third we get 2 so the total is 12.
Back to our algorithm, that example would give us:
c[1][0] = 1
c[1][1] = 1
c[2][0] = 2
c[2][1] = 2
c[3][0] = c[2][0] + c[2][1] = 4
c[3][1] = c[2][!S[1]] + c[1][!S[2]] = c[2][1] + c[1][0] = 3
c[4][0] = c[3][0] + c[3][1] = 7
c[4][1] = c[3][!S[1]] + c[2][!S[2]] = c[3][1] + c[2][0] = 5
So the final result is c[4][0] + c[4][1] = 12.
This is how I would implement it http://pastebin.com/fdDcpcNu. Could you check if it works?
If you don't understand my solution, just ask me.
Trust me, solution is correct.
Sorry, it is common bug, with russian side of this site. When i'm trying to answer on english message (written in english side of the site), the default language is russian, and i forged to switch it to english. I think this behaivor must be fixed, if your answer on english message, the language of answer must be english and CAN'T be russian. Stupid bug, sorry again.
UPD: BTW this yours comment must be in russian side, because it is reply of reply of my message