Thứ Hai, 24 tháng 12, 2012

Solution for Codeforces Round 157

Link: http://codeforces.com/blog/entry/6213


[problem:259A]

Obviously, the only correct rows are rows WBWBWBWB and BWBWBWBW. Only thing you need to do is to check whether each string is one of these. If yes then print YES, else print NO.

[problem:259B]

Since each number is less than or equal to 105, you can loop all possible a1, 1 values, the rest of cells can be calculated from this.

[problem:258A]

It's pretty easy to notice that you need to delete the first (from the left) 0-digit. The only catchy case is 111...111 — here you need to delete any of 1-digits.

[problem:258B]

First of all, lets think about the problem of finding array ci — the number of integers from 1 to m such, that the number of lucky digits is equal to i. It's pretty standart dynamic programminc problem, which can be solved with state [position][less][count].
It can be solved directly using DP, but to simplify a bit you can use brute froce (recursion) to brute all possible assignments of numbers of lucky digits in for all paries (up to 9 digits). Now you can divide all parties in several indepentent groups, each of which should contain the same number of lucky digits. Consider that the party of Litte Elephant is with number 1. Than assignment for the first position should have more digits than the sum of the rest (because of the statement). Since all groups are indepented (because there is no number that can have different number of lucky digits, obviously) you can find the number of resulting assignments for each group and find the final result by multiplying these all numbers and taking modulo 109 + 7.
Consider that you have group of size t, each number of which should contain l lucky digits. That it's pretty easy to understand that the number of assignment is equal to (cl)  (cl - 1)  (cl - 2)  ...  (cl - t + 1).

[problem:258C]

The complexity of the possible solution is O(nsqrt(n) log(n)). You can see that statementlcm(b1, b2, ..., bn) = max(b1, b2, ..., bn) is equal to statement "All the numbers b1, b2, ..., bn must divide max(b1, b2, ..., bn)". You can iterate that max(b1, b2, ..., bn), let it be equal to m. Find all divisors of m and sort them - p1, p2, ..., pk. For each i between 1 and k you can find (using simple DP) the number of numbers aj that pi ≤ aj < pi + 1 (if i = k than pi + 1 = max(a1, a2, ..., an) + 1), denote it asqi. Then the reuslt is equal to 1q1 2q2 3q3 ... pqp, because for each of the q1 numbers there is 1 way to assign, for each of q2 numbers there is 2 ways of assignments, and so on. But you should notice that if doing this problem in such way, you need to garantee that there is some i such bi = m. Hance you need from the last multiplier (pqp) subtract (p - 1)qp - all the ways that there is no number equal to m.

Thứ Hai, 17 tháng 12, 2012

Solution of Codeforces Round 156

Link: http://codeforces.ru/blog/entry/6161

255A - Greg's Workout

It is not hard problem. We must calculate sums of numbers for each group and print group with maximum count.

255B - Code Parsing

Not hard to see that after few operations of first type string will become: x..xy..y. After fer operations of second type, there will be only letters of one type, count of this letters will be: |count(x) — count(y)|

256A - Almost Arithmetical Progression

Заметим, что ответ это длина последовательности: a, b, a, b, ... где a и b — некоторые целые числа. Зафиксируем одно число (допустим a), будем перебирать число b, и считать какой мы получим ответ, если это будет последнее число в последовательности. Заметим, что для фиксированных a, b — ответ считается жадно. Так же будем действовать и тут. Будем искать последнее вхождение числа b до зафиксированного, что между ними есть число a, и будем брать ответ как длина до найденного числа +2 (икасть будем с помощью метода двух указателей). Так же нужно рассмотреть случай, когда это будет 1е или 2е вхождение в последовательность.
Так же существует решение с помощью динамического программирования.
Асимптотика обоих решений O(n^2).
Буду очень рад, если кто то напишет решение с лучшей асимптотикой.

256B - Mr. Bender and Square

Solution — binary search for answer. Next we have to calculate the area of a truncated square set at 45 degrees. This can be done as follows: Calculate its total area. Subtract area that cuts off the top line. Similarly, for the lower, left and right line. Add parts that are cutted by corners. You can write a function that finds the length of the truncation desired area, for that would not write a lot of code.

256C - Furlo and Rublo and Game

Note that after the first move any pile turns into a pile no larger than 1000000. We assume Grundy function for numbers less than 1 million. Grundy function is very small, you can start on the partial sums for each type of function that would quickly tell what function is in the interval, and which are not present. Knowing the answer is not difficult to find small response for all piles.

256D - Liars and Serge

If person say number x, and at all x was said by x persons, then we cannot tell anything about fixed person.
Now we understand which sequence are good for us. We will calculate their count wuth dynamic programming dp[n][m][k], n — which persons answers we set to the sequence right now, m — how mant persons gived theis answers, k — how many persons from them are liers.
Transfer:
dp[n][m][k]*cnk[N-m][n] -> dp[n+1][m+n][k]
dp[n][m][k]*cnk[N-m][p] -> dp[n+1][m+p][k+p] p = 1 .. N, p != n.
We assume, that N — total number of the persons. This solution get TLE, becouse complexity if O(N^4). We need to use precalc. It will not be so big, as N is power of 2.

256E - Lucky Arrays

Solution is — interval tree. We will save dynamic programming f[i,j] in each vertex, this dp means: in how many ways we can change all 0 to some numbers on interval, such that it will be valid and first element will be i and last will be j.
With normal implementation its easy to pass system tests.


Chủ Nhật, 16 tháng 12, 2012

Problem Mr. Bender and Square

Link: http://codeforces.com/problemset/problem/255/D

D. Mr. Bender and Square
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
Mr. Bender has a digital table of size n × n, each cell can be switched on or off. He wants the field to have at least c switched on squares. When this condition is fulfilled, Mr Bender will be happy.
We'll consider the table rows numbered from top to bottom from 1 to n, and the columns — numbered from left to right from 1 to n. Initially there is exactly one switched on cell with coordinates (x, y) (x is the row number, y is the column number), and all other cells are switched off. Then each second we switch on the cells that are off but have the side-adjacent cells that are on.
For a cell with coordinates (x, y) the side-adjacent cells are cells with coordinates (x - 1, y)(x + 1, y),(x, y - 1)(x, y + 1).
In how many seconds will Mr. Bender get happy?
Input
The first line contains four space-separated integers n, x, y, c (1 ≤ n, c ≤ 109; 1 ≤ x, y ≤ nc ≤ n2).
Output
In a single line print a single integer — the answer to the problem.
Sample test(s)
input
6 4 3 1
output
0
input
9 3 8 10
output
2
Note
Initially the first test has one painted cell, so the answer is 0. In the second test all events will go as is shown on the figure..

Thuật toán:
Để giải quyết bài toán trên, chúng ta giải bài toán con sau.
Chúng ta cần tính số ô chúng ta có được khi xuất phát từ ô (x, y) sau t bước.
Chúng ta gọi đó là hàm f(x,y,t).

Problem Almost Arithmetical Progression

Link: http://codeforces.com/problemset/problem/255/C

C. Almost Arithmetical Progression
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
Gena loves sequences of numbers. Recently, he has discovered a new type of sequences which he called an almost arithmetical progression. A sequence is an almost arithmetical progression, if its elements can be represented as:
  • a1 = p, where p is some integer;
  • ai = ai - 1 + ( - 1)i + 1·q (i > 1), where q is some integer.
Right now Gena has a piece of paper with sequence b, consisting of n integers. Help Gena, find there the longest subsequence of integers that is an almost arithmetical progression.
Sequence s1,  s2,  ...,  sk is a subsequence of sequence b1,  b2,  ...,  bn, if there is such increasing sequence of indexes i1, i2, ..., ik (1  ≤  i1  <  i2  < ...   <  ik  ≤  n), that bij  =  sj. In other words, sequence scan be obtained from b by crossing out some elements.
Input
The first line contains integer n (1 ≤ n ≤ 4000). The next line contains n integers b1, b2, ..., bn (1 ≤ bi ≤ 106).
Output
Print a single integer — the length of the required longest subsequence.
Sample test(s)
input
2
3 5
output
2
input
4
10 20 10 30
output
3
Note
In the first test the sequence actually is the suitable subsequence.
In the second test the following subsequence fits: 10, 20, 10.


Thuật toán: Quy hoạc động.
Gọi f[i,j] là kết quả khi xét từ đoạn i..j.
Nếu có a[j] trước a[i]: f[i][j] = f[pos[a[j]]][i] + 1.
Nếu chưa có a[j] nào trước a[i] thì f[i][j] = 2.
Đánh dấu a[i].

Code:

/*
Coder : Nguyen Duc Tam
template for contest
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<set>
#include<vector>
#include<utility>
#include<map>
#include<list>
#include<queue>
#include<deque>
#include<stack>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<iomanip>
#include<ctime>
#include<cctype>

using namespace std;

/*
define for statement loop
*/
#define REP(i, start, end, step) for(int i = start; i < end; i += step)
#define DOWN(i, start, end, step) for(int i = start; i > end; i -= step)
#define FOR(it,c) for(__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)
#define ALL(c) (c).begin(), (c).end()
#define SZ(x) ((int)(x).size())

/*
define operator bit
*/
#define L(x,i) ((x) << (i))
#define R(x,i) ((x) >> (i))
#define AND(a,b) ((a) & (b))
#define OR(a,b) ((a) | (b))
#define XOR(a,b) ((a) ^ (b))
#define NOT(a) (~(a))
#define SB(x,i) (OR((x), L(1, (i)))) // x | 1 << i
#define CB(x,i) (AND((x),NOT(L(1,(i))))) // x & ~(1 << i)
#define TB(x,i) (AND((x), L(1,(i)))) // x & (1 << i)

/*
define init data
*/
#define FILL(a,val) memset(a,val,sizeof(a));
#define INIT(a,l,r,val) REP(i,l,r,1) (a)[i] = val;

/*
define convert data
*/
#define DIG(c) (int)((c) - '0')
#define CHR(c) (char)((c) + '0')
#define LOW(c) (char)((c) + 32)
#define UPP(c) (char)((c) - 32)

/*
define math function
*/
#define sqr(a) (a) * (a)
#define abs(a) (a < 0 ? -(a) : (a))

/*
define find element in container very fast.
*/
#define LO(c,x) lower_bound(ALL(c),x)
#define UP(c,x) upper_bound(ALL(c),x)
#define IOF(c,x) distance((c).begin(), LO((c),x))
#define IOL(c,x) distance((c).begin(), UP((c),x))
#define IN(c,x) binary_search(ALL(c),x)
#define ER(c,x) equal_range(ALL(c),x)

/*
define geo
*/
#define DIS(p,q) sqrt(sqr(p.x - q.x) + sqr(p.y - q.y)) // khoang cach Euclide
#define DIM(p,q) abs(p.x - q.x) + abs(p.y - q.y) // khoang cach mahatan


/*
define constant
*/

#define EPS 1e-7
#define OO 1000000005
#define N 4005

#define X first
#define Y second

struct Point
{
double x, y;
Point(){}
Point(double x,double y):x(x), y(y){}
};

struct Node
{
int value;
Node* next;
Node(){}
Node(int value, Node* next):value(value),next(next){}
};

struct Edge
{
int src, dst, weight;
Edge(){}
Edge(int src, int dst, int weight):src(src), dst(dst), weight(weight){}

};

struct Compare
{

bool operator() (const int i, const int j)
{
return i > j;
}

/*
bool operator() (const Point& p, const Point& q)
{
return (p.x != q.x ? p.x < q.x : p.y < q.y);
}
*/
/*
bool operator()(const Edge& e, const Edge& f)
{
return (e.weight != f.weight ? e.weight > f.weight : e.src != f.src ?
e.src < f.src : e.dst < f.dst); // inverse weight
}
*/
};


const int DAY[13] = {-1,31,29,31,30,31,30,31,31,30,31,30,31};

const int dx4[4] = {-1, 0, 1, 0}; //U - R - D - L
const int dy4[4] = {0, 1, 0, -1};

const int dx8[8] = {-1, -1, 0, 1, 1, 1, 0, -1}; //U - UR - R - DR - D - DL - L - UL
const int dy8[8] = {0, 1, 1, 1, 0, -1, -1, -1};

typedef pair<int,int> II;
typedef pair<II,int> III;
typedef long long LL;
typedef unsigned long long ULL;
typedef unsigned char UC;

vector<int>::iterator it, low, up; // using lower_bound, upper_bound
pair<vector<int>::iterator, vector<int>::iterator > bound; // using function equal_range(first, last, x)
Compare comp;
Point p[2];

int n, a[N], res = 0, temp = 0, f[N][N], pos[1000005];

int main()
{
#define Off  true
if(Off)
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
}
cin >> n;
REP(i,0,n,1)
{
scanf("%d",&a[i]);
}
REP(j,1,n,1)
{
REP(i,0,n,1) pos[a[i]] = -1;
REP(i,0,j,1)
{
if(pos[a[j]] >= 0)
f[i][j] = f[pos[a[j]]][i] + 1;
else
f[i][j] = 2;
pos[a[i]] = i;
}
}
res = 1;
REP(i,0,n,1)
REP(j,i + 1,n,1)
res = max(res,f[i][j]);
cout << res << endl;
return 0;
}



Problem Code Parsing

Link: http://codeforces.com/problemset/problem/255/B

B. Code Parsing
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
Little Vitaly loves different algorithms. Today he has invented a new algorithm just for you. Vitaly's algorithm works with string s, consisting of characters "x" and "y", and uses two following operations at runtime:
  1. Find two consecutive characters in the string, such that the first of them equals "y", and the second one equals "x" and swap them. If there are several suitable pairs of characters, we choose the pair of characters that is located closer to the beginning of the string.
  2. Find in the string two consecutive characters, such that the first of them equals "x" and the second one equals "y". Remove these characters from the string. If there are several suitable pairs of characters, we choose the pair of characters that is located closer to the beginning of the string.
The input for the new algorithm is string s, and the algorithm works as follows:
  1. If you can apply at least one of the described operations to the string, go to step 2 of the algorithm. Otherwise, stop executing the algorithm and print the current string.
  2. If you can apply operation 1, then apply it. Otherwise, apply operation 2. After you apply the operation, go to step 1 of the algorithm.
Now Vitaly wonders, what is going to be printed as the result of the algorithm's work, if the input receives string s.
Input
The first line contains a non-empty string s.
It is guaranteed that the string only consists of characters "x" and "y". It is guaranteed that the string consists of at most 106 characters. It is guaranteed that as the result of the algorithm's execution won't be an empty string.
Output
In the only line print the string that is printed as the result of the algorithm's work, if the input of the algorithm input receives string s.
Sample test(s)
input
x
output
x
input
yxyxy
output
y
input
xxxxxy
output
xxxx
Note
In the first test the algorithm will end after the first step of the algorithm, as it is impossible to apply any operation. Thus, the string won't change.
In the second test the transformation will be like this:
  1. string "yxyxy" transforms into string "xyyxy";
  2. string "xyyxy" transforms into string "xyxyy";
  3. string "xyxyy" transforms into string "xxyyy";
  4. string "xxyyy" transforms into string "xyy";
  5. string "xyy" transforms into string "y".

Thuật toán : Nhận thấy, khi còn tồn tại hai kí tự x, y thì luôn thực hiện thao tác 1, hoặc 2. Do đó thuật toán kết thúc khi chỉ còn một kí tự duy nhất.
Code:

/*
Coder : Nguyen Duc Tam
template for contest
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<set>
#include<vector>
#include<utility>
#include<map>
#include<list>
#include<queue>
#include<deque>
#include<stack>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<iomanip>
#include<ctime>
#include<cctype>

using namespace std;

/*
define for statement loop
*/
#define REP(i, start, end, step) for(int i = start; i < end; i += step)
#define DOWN(i, start, end, step) for(int i = start; i > end; i -= step)
#define FOR(it,c) for(__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)
#define ALL(c) (c).begin(), (c).end()
#define SZ(x) ((int)(x).size())

/*
define operator bit
*/
#define L(x,i) ((x) << (i))
#define R(x,i) ((x) >> (i))
#define AND(a,b) ((a) & (b))
#define OR(a,b) ((a) | (b))
#define XOR(a,b) ((a) ^ (b))
#define NOT(a) (~(a))
#define SB(x,i) (OR((x), L(1, (i)))) // x | 1 << i
#define CB(x,i) (AND((x),NOT(L(1,(i))))) // x & ~(1 << i)
#define TB(x,i) (AND((x), L(1,(i)))) // x & (1 << i)

/*
define init data
*/
#define FILL(a,val) memset(a,val,sizeof(a));
#define INIT(a,l,r,val) REP(i,l,r,1) (a)[i] = val;

/*
define convert data
*/
#define DIG(c) (int)((c) - '0')
#define CHR(c) (char)((c) + '0')
#define LOW(c) (char)((c) + 32)
#define UPP(c) (char)((c) - 32)

/*
define math function
*/
#define sqr(a) (a) * (a)
#define abs(a) (a < 0 ? -(a) : (a))

/*
define find element in container very fast.
*/
#define LO(c,x) lower_bound(ALL(c),x)
#define UP(c,x) upper_bound(ALL(c),x)
#define IOF(c,x) distance((c).begin(), LO((c),x))
#define IOL(c,x) distance((c).begin(), UP((c),x))
#define IN(c,x) binary_search(ALL(c),x)
#define ER(c,x) equal_range(ALL(c),x)

/*
define geo
*/
#define DIS(p,q) sqrt(sqr(p.x - q.x) + sqr(p.y - q.y)) // khoang cach Euclide
#define DIM(p,q) abs(p.x - q.x) + abs(p.y - q.y) // khoang cach mahatan


/*
define constant
*/

#define EPS 1e-7
#define OO 1000000005
#define N 100005

#define X first
#define Y second

struct Point
{
double x, y;
Point(){}
Point(double x,double y):x(x), y(y){}
};

struct Node
{
int value;
Node* next;
Node(){}
Node(int value, Node* next):value(value),next(next){}
};

struct Edge
{
int src, dst, weight;
Edge(){}
Edge(int src, int dst, int weight):src(src), dst(dst), weight(weight){}

};

struct Compare
{

bool operator() (const int i, const int j)
{
return i > j;
}

/*
bool operator() (const Point& p, const Point& q)
{
return (p.x != q.x ? p.x < q.x : p.y < q.y);
}
*/
/*
bool operator()(const Edge& e, const Edge& f)
{
return (e.weight != f.weight ? e.weight > f.weight : e.src != f.src ?
e.src < f.src : e.dst < f.dst); // inverse weight
}
*/
};


const int DAY[13] = {-1,31,29,31,30,31,30,31,31,30,31,30,31};

const int dx4[4] = {-1, 0, 1, 0}; //U - R - D - L
const int dy4[4] = {0, 1, 0, -1};

const int dx8[8] = {-1, -1, 0, 1, 1, 1, 0, -1}; //U - UR - R - DR - D - DL - L - UL
const int dy8[8] = {0, 1, 1, 1, 0, -1, -1, -1};

typedef pair<int,int> II;
typedef pair<II,int> III;
typedef long long LL;
typedef unsigned long long ULL;
typedef unsigned char UC;

vector<int>::iterator it, low, up; // using lower_bound, upper_bound
pair<vector<int>::iterator, vector<int>::iterator > bound; // using function equal_range(first, last, x)
Compare comp;
Point p[2];

string s;
int len = 0,x = 0 ,y = 0;

int main()
{
#define Off  true
if(Off)
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
}
cin >> s;
len = s.size();
REP(i,0,len,1)
if(s[i] == 'x') x++;
else y++;
if(x == y) cout << "" << endl;
else if( x > y)
{
REP(i,0,x-y,1) printf("%c",'x');
}
else
{
REP(i,0,y-x,1) printf("%c",'y');
}
return 0;
}