Monday, 22 February 2016

C. Longest Regular Bracket Sequence
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
This is yet another problem dealing with regular bracket sequences.
We should remind you that a bracket sequence is called regular, if by inserting «+» and «1» into it we can get a correct mathematical expression. For example, sequences «(())()», «()» and «(()(()))» are regular, while «)(», «(()» and «(()))(» are not.
You are given a string of «(» and «)» characters. You are to find its longest substring that is a regular bracket sequence. You are to find the number of such substrings as well.
Input
The first line of the input file contains a non-empty string, consisting of «(» and «)» characters. Its length does not exceed 106.
Output
Print the length of the longest substring that is a regular bracket sequence, and the number of such substrings. If there are no such substrings, write the only line containing "0 1".
Sample test(s)
input
)((())))(()())
output
6 2
input
))(
output
0 1

Explanation

First of all, for each closing bracket in our string let's define 2 values:
  • d[j] = position of corresponding open bracket, or -1 if closing bracket doesn't belong to any regular bracket sequence.
  •  c[j] = position of earliest opening bracket, such that substring s(c[j], j) (both boundaries are inclusive) is a regular bracket sequence. Let's consider c[j] to be -1 if closing bracket doesn't belong to any regular bracket sequence.
It can be seen, that c[j] defines the beginning position of the longest regular bracket sequence, which will end in position j. So, having c[j] answer for the problem can be easily calculated. Both d[j] and c[j] can be found with following algorithm, which uses stack.
  1. Iterate through the characters of the string.
  2. If current character is opening bracket, put its position into the stack.
  3. If current character is closing bracket, there are 2 subcases:
  • Stack is empty - this means that current closing bracket doesn't have corresponding open one. Hence, both d[j] and c[j] are equal to -1.
  • Stack is not empty - we will have position of the corresponding open bracket on the top of the stack - let's put it to d[j] and remove this position from the stack. Now it is obvious, that c[j] is equal at least to d[j]. But probably, there is a better value for c[j]. To find this out, we just need to look at the position d[j] - 1. If there is a closing bracket at this position, and c[d[j] - 1] is not -1, than we have 2 regular bracket sequences s(c[d[j] - 1], d[j] - 1) and s(d[j], j), which can be concatenated into one larger regular bracket sequence. So we put c[j] to be c[d[j] - 1] for this case.
Code
#include<bits/stdc++.h> 
using namespace std;
 int c[2000100]; int d[2000100];
 stack<int> st;
 int main()
 { string s;
 cin>>s; 
 int l=s.length();
 int b=0;
 int al=-1,ar=-1; int ans=0; int res=0; int cnt=0; memset(d,-1,sizeof(d)); memset(c,-1,sizeof(c)); for(int i=1;i<=l;i++) { if(s[i-1]=='(') st.push(i); else { if(st.empty()) { c[i]=-1; d[i]=-1; } else { int val=st.top(); st.pop(); d[i]=val; c[i]=val; if(d[i]-1>=1 && s[d[i]-2]==')' && c[d[i]-1]!=-1) { // cout<<"i here "<<d[i]-1<<" "<<c[d[i]-1]<<endl; c[i]=min(c[i],c[d[i]-1]); } } } } // for(int i=1;i<=l;i++) // cout<<c[i]<<" "; // cout<<endl; ans=0; for(int i=1;i<=l;i++) { if(c[i]!=-1) ans=max(ans,(i-c[i]+1)); } if(ans==0) { cout<<"0 1"<<endl; return 0; } else { int cnt=0; for(int i=1;i<=l;i++) { if(c[i]!=-1) if(i-c[i]+1==ans) cnt++; } cout<<ans<<" "<<cnt<<endl; } return 0; }

Saturday, 20 February 2016

GNY07H - Tiling a Grid With Dominoes


We wish to tile a grid 4 units high and N units long with rectangles (dominoes) 2 units by one unit (in either orientation). For example, the figure shows the five different ways that a grid 4 units high and 2 units wide may be tiled.
Write a program that takes as input the width, W, of the grid and outputs the number of different ways to tile a 4-by-Wgrid.

Input

The first line of input contains a single integer N, (1 ≤ N ≤ 1000) which is the number of datasets that follow.
Each dataset contains a single decimal integer, the width, W, of the grid for this problem instance.

Output

For each problem instance, there is one line of output: The problem instance number as a decimal integer (start counting at one), a single space and the number of tilings of a 4-by-W grid. The values of W will be chosen so the count will fit in a 32-bit integer.


Explanation

Let T(n) be the number of ways one can tile a 3×n board with 2×1 tiles. Also, let P(n) be the number of ways one can tile a 3×n board with one corner removed with 2×1 tiles. Assumen sufficiently large (>= 4).
Then consider how you can start the tiling from the left (or right, doesn't matter).
You can place the tile covering the top left corner in two ways, vertical or horizontal. If you place it vertical, the tile covering the bottom left corner must be placed horizontally, giving a configuration
|
==
That leaves P(n-1) ways to tile the remaining part. If you place it horizontally, you can place the tile covering the bottom left corner either horizontally or vertically. If you place it vertically, you are in the same situation as before, just reflected, and if you place it horizontally, you must place a tile horizontally between them,
==
==
==
leaving you with a 3×(n-2) board to tile. Thus
T(n) = T(n-2) + 2*P(n-1)              (1)
Now, considering the 3×(n-1) board with one removed (already covered) corner (let's assume top left), you can either place a tile vertically below it, giving
=
|
and leaving you with a 3×(n-2) board to tile, or you can place two tiles horizontally below it, giving
=
==
==
and then you have no choice but to place another tile horizontally at the top, leaving you
===
==
==
with a 3×(n-3) board minus a corner,
P(n-1) = T(n-2) + P(n-3)
Adding up,
T(n) = T(n-2) + 2*(T(n-2) + P(n-3))
     = 3*T(n-2) + 2*P(n-3)                            (2)
But, using (1) with n-2 in place of n, we see that
T(n-2) = T(n-4) + 2*P(n-3)
or
2*P(n-3) = T(n-2) - T(n-4)
Inserting that into (2) yields the recurrence
T(n) = 4*T(n-2) - T(n-4)
q.e.d.


Solution

#include<bits/stdc++.h>
using namespace std;
int ha[30];
int hb[30];

#define ll long long int
ll dp[40];
int solve(int n)
{
if(n==0)
return 1;
if(n==1)
return 0;
if(n==3)
return 0;
if(n==2)
return 3;
if(n<0)
return 0;
 if(dp[n]!=-1)
 return dp[n];
 else
 {
   
 ll res=0;
 res+=4*solve(n-2)-solve(n-4);
 dp[n]=res;
 return res;}
}
int main()
{
     int n;
     memset(dp,-1,sizeof(dp));
     while(1)
 {
  cin>>n;
      if(n==-1)
  break;
  else 
  {
    ll res=solve(n);
    cout<<res<<endl;
}  
 }
 return 0;
}

Saturday, 30 January 2016



Combinatorics



Meera bought a house on Mars, and plans to decorate it with chains of alien flowers. Each flower is either red (R) or blue (B), and Meera knows how many occurrences of RRRBBB, and BR she wants to see in a chain.
The diagram below shows a flower chain of length 10:
In this example, RR occurs 2 times (at positions 0 and 4), RB occurs 3 times (at positions 15, and 7), BB occurs 1 time (at position 2), and BR occurs 3 times (at positions 36, and 8).
Meera wants your help determining how many different chains with positive length can be made. Given A,B,C, and D, find the number of different chains having occurrences of RR,RBBB and BR equal to inputs A,B,C, and D, respectively. As the answer can be very large, your printed output should be answer % (109+7).
Input Format
One line of space-separated, non-negative integers: A (occurrences of RR), B (occurrences of RB), C (occurrences of BB), and D (occurrences of BR), respectively.
Constraints
For 20% Points: 0A,B,C,D4
For 50% Points: 0A,B,C,D102
For 100% Points: 0A,B,C,D105
Output Format
Find the number of chains having A,B,C, and D occurrences of RRRBBB, and BR, respectively, and print the answer % (109+7).
Sample Input
1 1 2 1
Sample Output
5
Explanation
  The code goes here
/***********Template Starts Here***********/
#include <bits/stdc++.h>

#define pb push_back
#define nl puts ("")
#define sp printf ( " " )
#define phl printf ( "hello\n" )
#define ff first
#define ss second
#define POPCOUNT __builtin_popcountll
#define RIGHTMOST __builtin_ctzll
#define LEFTMOST(x) (63-__builtin_clzll((x)))
#define MP make_pair
#define FOR(i,x,y) for(vlong i = (x) ; i <= (y) ; ++i)
#define ROF(i,x,y) for(vlong i = (y) ; i >= (x) ; --i)
#define CLR(x,y) memset(x,y,sizeof(x))
#define UNIQUE(V) (V).erase(unique((V).begin(),(V).end()),(V).end())
#define MIN(a,b) ((a)<(b)?(a):(b))
#define MAX(a,b) ((a)>(b)?(a):(b))
#define NUMDIGIT(x,y) (((vlong)(log10((x))/log10((y))))+1)
#define SQ(x) ((x)*(x))
#define ABS(x) ((x)<0?-(x):(x))
#define FABS(x) ((x)+eps<0?-(x):(x))
#define ALL(x) (x).begin(),(x).end()
#define LCM(x,y) (((x)/gcd((x),(y)))*(y))
#define SZ(x) ((vlong)(x).size())
#define NORM(x) if(x>=mod)x-=mod;
#define ODD(x) (((x)&1)==0?(0):(1))

using namespace std;

typedef long long vlong;
typedef unsigned long long uvlong;
typedef pair < int, int > pii;
typedef pair < vlong, vlong > pll;
typedef vector<pii> vii;
typedef vector<int> vi;

const vlong inf = 2147383647;
const double pi = 2 * acos ( 0.0 );
const double eps = 1e-9;

#ifdef forthright48
     #include <ctime>
     clock_t tStart = clock();
     #define debug(args...) {dbg,args; cerr<<endl;}
    #define timeStamp debug ("Execution Time: ", (double)(clock() - tStart)/CLOCKS_PER_SEC)
#else
    #define debug(args...)  // Just strip off all debug tokens
    #define timeStamp
#endif

struct debugger{
    template<typename T> debugger& operator , (const T& v){
        cerr<<v<<" ";
        return *this;
    }
}dbg;

//int knightDir[8][2] = { {-2,1},{-1,2},{1,2},{2,1},{2,-1},{-1,-2},{1,-2},{-2,-1} };
//int dir4[4][2] = {{-1,0},{0,1},{1,0},{0,-1}};

inline vlong gcd ( vlong a, vlong b ) {
    a = ABS ( a ); b = ABS ( b );
    while ( b ) { a = a % b; swap ( a, b ); } return a;
}

vlong ext_gcd ( vlong A, vlong B, vlong *X, vlong *Y ){
    vlong x2, y2, x1, y1, x, y, r2, r1, q, r;
    x2 = 1; y2 = 0;
    x1 = 0; y1 = 1;
    for (r2 = A, r1 = B; r1 != 0; r2 = r1, r1 = r, x2 = x1, y2 = y1, x1 = x, y1 = y ) {
        q = r2 / r1;
        r = r2 % r1;
        x = x2 - (q * x1);
        y = y2 - (q * y1);
    }
    *X = x2; *Y = y2;
    return r2;
}

inline vlong modInv ( vlong a, vlong m ) {
    vlong x, y;
    ext_gcd( a, m, &x, &y );
    if ( x < 0 ) x += m; //modInv is never negative
    return x;
}

inline vlong power ( vlong a, vlong p ) {
    vlong res = 1, x = a;
    while ( p ) {
        if ( p & 1 ) res = ( res * x );
        x = ( x * x ); p >>= 1;
    }
    return res;
}

inline vlong bigmod ( vlong a, vlong p, vlong m ) {
    vlong res = 1 % m, x = a % m;
    while ( p ) {
        if ( p & 1 ) res = ( res * x ) % m;
        x = ( x * x ) % m; p >>= 1;
    }
    return res;
}

/***********Template Ends Here***********/
int mod = 1000000000 + 7;
vlong fact[2000000], inv[2000000];

void precal() {
    fact[0] = 1;
    FOR(i,1,1000000) {
        fact[i] = fact[i-1] * i;
        fact[i] %= mod;
    }

    FOR(i,0,1000000) {
        inv[i] = modInv( fact[i], mod );
    }
}

vlong combo ( int n, int k ) {
    if ( n == k ) return 1;
    if ( n == 0 ) return 0;
    if ( k == 0 ) return 0;

    int x = n - 1;
    int y = k - 1;

    vlong res = ( inv[x-y] * inv[y] ) % mod; ///Calculate nck(x,y)
    res *= fact[x];
    res %= mod;
    return res;
}

int solve ( int a, int b, int c, int d ) {
    if ( ABS(b-d) > 1 ) return 0;

    int tr = a + d;
    int tb = b + c;

    vlong res = 0;

    ///Start with R
    if ( b == d || b > d ) {
        res += combo ( tr + 1, d + 1 ) * combo ( tb, b );
        res %= mod;
    }

    ///Start with B
    if ( b == d || d > b ) {
        res += combo ( tr, d ) * combo ( tb + 1, b + 1 );
        res %= mod;
    }

    return res;
}

void solution() {

    int a, b, c, d;
    scanf ( "%d %d %d %d", &a, &b, &c, &d );

    printf ( "%d\n", solve ( a, b, c, d ) );

}

int main () {
    precal();

    solution();

    return 0;
}



The 5 flower chains having exactly 1,1,2, and 1 occurrences of RRRBBB and BR are:
Editorial by Mohammad Samiul Islam
We are given number of occurances of RRRBBBBR (A,B,C,D) and we need to find number of strings which have same occurances.

A string is either of form {R}{B}{R}{B}... or {B}{R}{B}{R}... where {X} represents one or more of X.

Let use ignore RR and BB for now. How many strings can we make using RB and BR?

If B==D, then there are two ways:
  • {R}{B}{R}...{R}, where {R} occurs D+1 times and {B} occurs B times.
  • {B}{R}{B}...{B}, where {R} occurs D times and {B} occurs B+1 times.

If B==D+1, then there is one way: {R}{B}{R}{B}...{B}, where {R} occurs D+1 times and {B} occurs B times.

If B+1==D, then there is one way: {B}{R}{B}{R}...{R}, where {R} occurs D times and {B} occurs B+1 times.

If |DB|>1, then there is no way.

Once we fix number ways we can place RB and BR, the rest is simple combinatorics. Each of {R} is a container that will contain one or more R and {B} is a container that will contain one or more B. For each way, we know number of containers and total number of flowers we want to place.

Number of ways we can place X items in Y containers such that each container contains atleast 1 item is (X1Y1).

Calculating binomial coefficient will take logarithm time here, but assuming we precalculated those, it takes O(1) time complexity.

Special Case

Seems like few people were having trouble with 0,0,0,0 input. The answer is 2. How? We can form the following two strings "R" and "B". Both of them has length 1 and contains no occurences of RRRB,BBBR.














/***********Template Starts Here***********/
#include <bits/stdc++.h>

#define pb push_back
#define nl puts ("")
#define sp printf ( " " )
#define phl printf ( "hello\n" )
#define ff first
#define ss second
#define POPCOUNT __builtin_popcountll
#define RIGHTMOST __builtin_ctzll
#define LEFTMOST(x) (63-__builtin_clzll((x)))
#define MP make_pair
#define FOR(i,x,y) for(vlong i = (x) ; i <= (y) ; ++i)
#define ROF(i,x,y) for(vlong i = (y) ; i >= (x) ; --i)
#define CLR(x,y) memset(x,y,sizeof(x))
#define UNIQUE(V) (V).erase(unique((V).begin(),(V).end()),(V).end())
#define MIN(a,b) ((a)<(b)?(a):(b))
#define MAX(a,b) ((a)>(b)?(a):(b))
#define NUMDIGIT(x,y) (((vlong)(log10((x))/log10((y))))+1)
#define SQ(x) ((x)*(x))
#define ABS(x) ((x)<0?-(x):(x))
#define FABS(x) ((x)+eps<0?-(x):(x))
#define ALL(x) (x).begin(),(x).end()
#define LCM(x,y) (((x)/gcd((x),(y)))*(y))
#define SZ(x) ((vlong)(x).size())
#define NORM(x) if(x>=mod)x-=mod;
#define ODD(x) (((x)&1)==0?(0):(1))

using namespace std;

typedef long long vlong;
typedef unsigned long long uvlong;
typedef pair < int, int > pii;
typedef pair < vlong, vlong > pll;
typedef vector<pii> vii;
typedef vector<int> vi;

const vlong inf = 2147383647;
const double pi = 2 * acos ( 0.0 );
const double eps = 1e-9;

#ifdef forthright48
     #include <ctime>
     clock_t tStart = clock();
     #define debug(args...) {dbg,args; cerr<<endl;}
    #define timeStamp debug ("Execution Time: ", (double)(clock() - tStart)/CLOCKS_PER_SEC)
#else
    #define debug(args...)  // Just strip off all debug tokens
    #define timeStamp
#endif

struct debugger{
    template<typename T> debugger& operator , (const T& v){
        cerr<<v<<" ";
        return *this;
    }
}dbg;

//int knightDir[8][2] = { {-2,1},{-1,2},{1,2},{2,1},{2,-1},{-1,-2},{1,-2},{-2,-1} };
//int dir4[4][2] = {{-1,0},{0,1},{1,0},{0,-1}};

inline vlong gcd ( vlong a, vlong b ) {
    a = ABS ( a ); b = ABS ( b );
    while ( b ) { a = a % b; swap ( a, b ); } return a;
}

vlong ext_gcd ( vlong A, vlong B, vlong *X, vlong *Y ){
    vlong x2, y2, x1, y1, x, y, r2, r1, q, r;
    x2 = 1; y2 = 0;
    x1 = 0; y1 = 1;
    for (r2 = A, r1 = B; r1 != 0; r2 = r1, r1 = r, x2 = x1, y2 = y1, x1 = x, y1 = y ) {
        q = r2 / r1;
        r = r2 % r1;
        x = x2 - (q * x1);
        y = y2 - (q * y1);
    }
    *X = x2; *Y = y2;
    return r2;
}

inline vlong modInv ( vlong a, vlong m ) {
    vlong x, y;
    ext_gcd( a, m, &x, &y );
    if ( x < 0 ) x += m; //modInv is never negative
    return x;
}

inline vlong power ( vlong a, vlong p ) {
    vlong res = 1, x = a;
    while ( p ) {
        if ( p & 1 ) res = ( res * x );
        x = ( x * x ); p >>= 1;
    }
    return res;
}

inline vlong bigmod ( vlong a, vlong p, vlong m ) {
    vlong res = 1 % m, x = a % m;
    while ( p ) {
        if ( p & 1 ) res = ( res * x ) % m;
        x = ( x * x ) % m; p >>= 1;
    }
    return res;
}

/***********Template Ends Here***********/
int mod = 1000000000 + 7;
vlong fact[2000000], inv[2000000];

void precal() {
    fact[0] = 1;
    FOR(i,1,1000000) {
        fact[i] = fact[i-1] * i;
        fact[i] %= mod;
    }

    FOR(i,0,1000000) {
        inv[i] = modInv( fact[i], mod );
    }
}

vlong combo ( int n, int k ) {
    if ( n == k ) return 1;
    if ( n == 0 ) return 0;
    if ( k == 0 ) return 0;

    int x = n - 1;
    int y = k - 1;

    vlong res = ( inv[x-y] * inv[y] ) % mod; ///Calculate nck(x,y)
    res *= fact[x];
    res %= mod;
    return res;
}

int solve ( int a, int b, int c, int d ) {
    if ( ABS(b-d) > 1 ) return 0;

    int tr = a + d;
    int tb = b + c;

    vlong res = 0;

    ///Start with R
    if ( b == d || b > d ) {
        res += combo ( tr + 1, d + 1 ) * combo ( tb, b );
        res %= mod;
    }

    ///Start with B
    if ( b == d || d > b ) {
        res += combo ( tr, d ) * combo ( tb + 1, b + 1 );
        res %= mod;
    }

    return res;
}

void solution() {

    int a, b, c, d;
    scanf ( "%d %d %d %d", &a, &b, &c, &d );

    printf ( "%d\n", solve ( a, b, c, d ) );

}

int main () {
    precal();

    solution();

    return 0;
}