Git Hashes

Git sometimes does things like magic. But the magic it shows how it stores it information internally. Let’s discuss the fundamentals.

Okay, we have created an empty directory named git-internal and we initialised git in that directory. We can see the basic file structure inside .git folder which is the folder used by git to store all information.

Lets create a file main.go and modify so that after modification, the directory and content looks like this:

There is no change in .git directory so far. Let’s use git hash-object command to find out the SHA1 hash of main.go file using git hash-object main.go. git hash-object gives you the object id of a file, in our case main.go

Now, let’s add main.go file to git using git add main.go and see what has been changed in .git directory

If you notice then, you can see the SHA1 hash from the git hash-object main.go is used to denote a directory and a file. More specifically , first two character is used as a upper level directory, and the rest of 38 character is used to denote a file inside that directory. It’s a zlib compressed file which contains a header and the content of the file.

I suppose, this doesn’t answer clearly what is happening behind the curtain. So let’s dive into details.
In git, there is three kinds of objects

  • blobs
  • trees
  • commits

we have our main.go file. The process of generating the corresponding filename(in our case 99/fd8050e485c174e01c4e074041e41ae09bae59) and content of the file is as follows:

  • Git first constructs a header which starts by identifying the type of object — in this case, a blob. To that first part of the header, Git adds a space followed by the size in bytes of the content, and adding a final null byte
  • Git concatenates the header and the original content and then calculates the SHA-1 checksum of that new content. This SHA1 has is the same as git hash-object main.go output

Now that we know, how the SHA1 hash and the file name corresponding to that file is created. The content of that file is the zlib compressed version of value stored in store variable. To verify that, I have written a piece of code, that opens the file, decompresses using zlib format, and displays into terminal

Now this point, it should be clear that only the content of the file matters, the name or file permission doesn’t matter to this point at all. The file is just a zlib compressed data(header + file content). To prove this point, see the following picture:

Okay, now let’s create a commit and see what’s the status ? So, we run git commit -m "first commit" and let’s see what is changed in the object directory

Now, we see two new file created on this directory. So, we know 99/fd8050e485c174e01c4e074041e41ae09bae59 is correspond to the file main.go then what are the other files. To find out what is the type of object we can use git cat-file command. (Provide content or type and size information for repository objects)

So, we can see the other two types of objects in git. The tree type objects, basically holds the information

  • File permission
  • type of objects is has inside(blob/tree)
  • hash of the objects
  • name of the blob/tree(this is where, git knows about the existance of a file)

To generate the hash of the tree(b52e25f217248e21dec163465bd111bb6f723f0e)

We can see the format of the file, and how we generate these values.

For commit objects, we can see the same picture. Lets run this same thing for commit object file

Here we can see, the commit file 36/29dca9fc3a11108fcd229c8ed082ffa8761192 contains a header commit 197 and then information about tree, author, commiter, timestamp and commit message in zlib format.

The process to generate 40 byte hash and generate file content is exactly same, just the header and what information is included is different. 
store =  \0
Hash = SHA1(store)
file_name = Hash[0:2]/Hash[2:]
file_content = zlib_compressed(store)

Aside

Everyday Git

Git is the most popular version control system in modern tech world. The usage of version control system is to somehow manage all the versions of your work. Before going to the using of git, lets learn different version control system

  • Local version control: Limited to one computer, Store the difference between two versions in the disk in a special format. You can get any versioned file by adding the patch (Example: RCS)
  • Centralised version control: Many user, but only one server that contains the versioned file. Backwards is, single point of failure. If the server goes down, nobody can collaborate. If the file system crashes/ get corrupted and proper backup is not kept, then all the history loses except the snapshots stored in the users machine (Ex: CVS, Subversion, Perforce)
  • Distributed version control: Client check out recent version of files as well as all the history of the repository. These client copy is actually identical to the copy stored in the server. ( Git, Mercurial)

Git Philosophy :

  • Snapshots, Not difference: CVS, Subversion and other version control system stores a list of files, and the difference in each file for each version. Instead, Git thinks of its data more like a series of snapshots of a miniature filesystem. With Git, every time you commit, Git basically takes a picture of what all your files look like at that moment and stores a reference to that snapshot. To be efficient, if files have not changed, Git doesn’t store the file again, just a link to the previous identical file it has already stored.
Credit: Pro Git
  • Nearly every operation is local: As local machine is perfect replica of the git remote server, you can almost do many things when you are off network or out of VPN.
  • Data integrity: Everything is checksummed. Git preserve integrity by checking this sum. It uses SHA-1 hash to maintain and changes in file system.
  • Data Safety: If you commit something in git, it is very much impossible to lose that piece of data.
  • Three states: Modified, Staged, Commited

Number Theory for Competitive Programming

For contest programmers, Math problems are common. So, It is going to be a long post. and will updated now and then. I will try to cover as many idea as possible in this tutorial.

GCD,LCM,EUCLID

g = gcd(a,b) = Meaning the greatest Common divisor of a and b.Highest number which divides both a and b.
l = lcm(a,b) = Meaning the least common multiple.
Properties:

  • gcd(a/g,b/g)=1. This property is used to reduce fraction such that numerator and denominator has no common divisor.
  • gcd is assosiative, gcd(a,b,c) = gcd(a,gcd(b,c)) = gcd(b,gcd(a,c)) = .. for all possible combination.
  • gcd(a,b)*lcm(a,b) = a*b. This is used to calculate lcm.
  • If a = p_1^{a1}*p_2^{a2}*.... p_r^{ar} and b = p_1^{b1}*p_2^{b2}*.... p_r^{br}  then gcd(a,b) = p_1^{min(a1,b1)}*p_2^{min(a2,b2)}*.... p_r^{min(ar,br)}

  • Euclid Algorithm for finding gcd(a,b) : O(log(min(a,b))

    
    int gcd(int a,int b)
    {
    	if(b==0)return 1;
    	return gcd(b,a%b);
    }
    
    int lcm(long long a,long long b) 
    {
    	return a/gcd(a,b)*g;
    }
    

    Bézout's identity: If gcd(a,b)=g, then, we can certainly find two integer x,and y such that a*x+b*y=g.

    This is called extended euclid algorithm. Now to find this x and y, we need to trace back the process of finding gcd.

    int extended_euclid(int a, int b, int &x, int &y) {
    	int xx = y = 0;
    	int yy = x = 1;
    	while (b) {
    		int q = a / b;
    		int t = b; b = a%b; a = t;
    		t = xx; xx = x - q*xx; x = t;
    		t = yy; yy = y - q*yy; y = t;
    	}
    	return a;
    }
    

    Modular Inverse: Given a and n, compute x such that a*x = 1 (mod n).

    // Return -1, if no solution.
    int mod_inverse(int a, int n) {
    	int x, y;
    	int g = extended_euclid(a, n, x, y);
    	if (g > 1) return -1;
    	return mod(x, n);
    }
    

    Linear Diophantine Equation Solution: Given, a*x+b*y=c. Find valid x and y if possible.

    bool linear_diophantine (int a, int b, int c, int & x0, int & y0, int & g) {
    	g = extended_euclid (abs(a), abs(b), x0, y0);
    	if (c % g != 0)
    		return false;
    	x0 *= c / g;
    	y0 *= c / g;
    	if (a < 0)   x0 *= -1;
    	if (b < 0)   y0 *= -1;
    	return true;
    }
    

    Now is the values of x and y are unique? No.

    for each integer k,
    x1 = x + k * b/g
    y1 = y - k * a/g
    is a solution to the equation where g = gcd(a,b).
    

    Now How many solution where x in range[x1,x2] and y in range[y1,y2] ?

    void shift_solution (int & x, int & y, int a, int b, int cnt) {
    	x += cnt * b;
    	y -= cnt * a;
    }
    int find_all_solutions(int a,int b,int c,int &minx,int &maxx,int &miny,int &maxy)
    {
    	int x,y,g;
    	if(linear_diophantine(a,b,c,x,y,g) == 0) return 0;
    	a/=g, b/=g;
    	int sign_a = a>0 ? +1 : -1;
    	int sign_b = b>0 ? +1 : -1;
    
    	shift_solution (x, y, a, b, (minx - x) / b);
    	if (x < minx)
    		shift_solution (x, y, a, b, sign_b);
    	if (x > maxx)
    		return 0;
    	int lx1 = x;
     
    	shift_solution (x, y, a, b, (maxx - x) / b);
    	if (x > maxx)
    		shift_solution (x, y, a, b, -sign_b);
    	int rx1 = x;
     
    	shift_solution (x, y, a, b, - (miny - y) / a);
    	if (y < miny)
    		shift_solution (x, y, a, b, -sign_a);
    	if (y > maxy)
    		return 0;
    	int lx2 = x;
     
    	shift_solution (x, y, a, b, - (maxy - y) / a);
    	if (y > maxy)
    		shift_solution (x, y, a, b, sign_a);
    	int rx2 = x;
     
    	if (lx2 > rx2)
    		swap (lx2, rx2);
    	int lx = max (lx1, lx2);
    	int rx = min (rx1, rx2);
     
    	return (rx - lx) / abs(b) + 1;
    }
    

    For Futhre Reading About this:
    1.http://e-maxx.ru/algo/euclid_algorithm
    2. http://e-maxx.ru/algo/extended_euclid_algorithm
    3. http://e-maxx.ru/algo/diofant_2_equation
    4. http://e-maxx.ru/algo/diofant_1_equation
    5. http://discuss.codechef.com/questions/20842/a-tutorial-on-the-extended-euclids-algorithm

    Problems to solve:

    Euler’s totient function

    In number theory, \phi(n) denotes the number of integers <=n which is relatively prime to n. Two numbers a and b are called relatively prime, if gcd(a,b) = 1. here gcd denotes greatest common divisor.
    For example: n = 9, there are the six numbers 1, 2, 4, 5, 7 and 8.They are all relatively prime to 9, but the other three numbers in this range, 3, 6, and 9 are not, because gcd(9, 3) = gcd(9, 6) = 3 and gcd(9, 9) = 9. Therefore, φ(9) = 6.

    Properties:

    1. Euler’s totient function is a multiplicative function, meaning that if two numbers m and n are relatively prime, then \phi(mn) = \phi(m)\phi(n)
    2. \phi(p^k) = p^k-p^{k-1}
    Proof: since p is a prime number the only possible values of gcd(p^k, m) are 1, p, p^2, ..., p^k, and the only way for gcd(p^k, m) to not equal 1 is for m to be a multiple of p. The multiples of p that are less than or equal to p^k are p, 2p, 3p, ...,p^{k-1}p = p^k and there are p^{k-1} of them. Therefore, the other p^k - p^{k-1} numbers are all relatively prime to p^k.
    3. From Wiki.
    1

    Now Using these formula,
    36 = 2^2 * 3^2.
    \phi(36) = 36*(1-\frac{1}{2})*(1-\frac{1}{3}) = 12

    Problem Using Phi Function

    And many more will be added….

    Uva Volume 11500-11599

    Uva 11500

    Link : 11500
    Idea :
    From a state (a,b) we can go either (a+d,b-d) or (a-d,b+d) . So we can define our recursive relation here.
    P(a,b) = AT/6 * P(a + d, max(0,b-d) ) + (6-AT)/6 * P(max(0,a-d),b+d)
    Base case :
    P(i,0) = 1, for i = 0 … a
    P(0,i) = 0, for i = 1 … b

    So for each step , we can build an equation and using gaussian elimination we can found P(a,b)

    Click to See Code
    #include <bits/stdc++.h>
    using namespace std;
    
    namespace gauss {
        double EPS = 1e-8;
        typedef double T;
        typedef vector<T> VT;
        typedef vector<VT> VVT;
        
        
        int Gauss(VVT &a)
        {
            int n = a.size(), m= a[0].size();
            int r = 0;
            for(int c = 0; c < m - 1 && r < n ; c ++ ) {
                int j = r;
                for(int i = r+1; i < n; i ++ ) {
                    if(fabs(a[i][c]) > fabs(a[j][c])) j= i;
                }
                if(fabs(a[j][c]) < EPS) continue;
                swap(a[j],a[r]);
                T s = 1./a[r][c];
                for(int i = 0; i < m ; i ++ ) a[r][i] *= s;
                for(int i=0;i < n ;i ++) if(i!=r) {
                    T t = a[i][c];
                    for(int j = 0; j < m ; j ++ ) a[i][j] -= t * a[r][j];
                }
                r++;
            }
            return r;
            
        }
    }
    using namespace gauss;
    
    int main()
    {
        int a,b,l,w;
        while(scanf("%d %d %d %d",&a,&b,&l,&w)==4 ) {
            if(a+b+l+w == 0) break;
            map<pair<int,int> ,int>Map;
            int cnt = 0;
            for(int i = 0; ; i ++ ) {
                Map[make_pair(a+i*w, max(0,b-i*w))] =cnt ++;
                if(b-i * w <= 0 ) break;
            }
            for(int i = 1; ; i ++ ) {
                Map[make_pair(max( a - i*w , 0), b + i * w)] =cnt ++;
                if(a-i * w <= 0 ) break;
            }
            int Dim = Map.size();
            VVT A ( Map.size() , VT ( Map.size() + 1, 0) );
            for(auto a: Map ) {
                pair<int,int> P = a.first ;
                if(P.first == 0 || P.second == 0 ) {
                    A[Map[P]][Map[P]] = 1;
                    A[Map[P]][Dim] = (P.first ? 1 : 0);
                    continue;
                }
                pair<int,int> F = make_pair(P.first + w , max(0, P.second - w));
                pair<int,int> S = make_pair(max(P.first - w ,0 ) , P.second + w);
                A[Map[P]][Map[P]] = 1;
                A[Map[P]][Map[F]] = -1. * l / 6;
                A[Map[P]][Map[S]] = -1. * (6-l) / 6;
                A[Map[P]][Dim]  = 0;
            }
            Gauss(A);
            
            printf("%.1lf\n",A[Map[make_pair(a,b)]][Dim] * 100);
        }
    }
    

    Uva 11503

    Link: 11503 – Virtual Friends

    Solution:Disjoint set

    * Map the string into integer.
    * For each friendship(new edge), If they are already connected,then output the Size of the connected component .if not, Merge them and increase the size of a component

    This Problem is basic of Disjoint Set union.

    Click to See Code
    #include <bits/stdc++.h>
    #include <sstream>
    using namespace std;
    #define MX 100005
    
    
    string s1,s2;
    map<string, int> kl;
    int para[MX];
    int size[MX];
    int find_represent(int a)
    {
        if(para[a]==a) return a;
        else return para[a] = find_represent(para[a]);
    }
    
    int friendship(int a,int b)
    {
        int u = find_represent(a);
        int v = find_represent(b);
        
        if(u!=v){
            para[u]=v;
            size[v] = size[v] + size[u];
        }
        return size[v];
    }
    
    int main()
    {
        int test,f,inx;
        cin>>test;
        
        while (test--) {
            cin>>f;
            inx=0;
            for(int i=0;i<MX;i++) {para[i]=i;size[i]=1;}
            while (f--) {
                cin>>s1>>s2;
                if (kl.count(s1)==0) {
                    kl[s1]=inx++;
                }
                if(kl.count(s2)==0) kl[s2]=inx++;
                
                cout<<friendship(kl[s1],kl[s2])<<"\n";
            }
            kl.clear();
            
        }
        return 0;
    }
    
    
    
    

    Uva 11505

    Link: Uva 11505
    Idea:
    Easy Problem. Using Vector Translation & Rotation. I use Stanford Geometry Template.
    Starting point can be anything, the answer is same. So Pick(0,0) as starting position and initial direction is in +x axis (denoted by a directional vector (1,0))
    When we found fd or bk command, we move d distance towards the directional vector.
    for lt or rt command , we rotate the directional vector
    After executing all commands suppose we are point (x,y) then ans = nearest integer ( sqrt (x*x + y * y ))

    Click to See Code
    #include <bits/stdc++.h>
    using namespace std;
    struct PT {
        double x,y;
        PT(double x,double y):x(x),y(y){}
        PT operator + (const PT &p) const {return PT(x+p.x,y+p.y);}
        PT operator - (const PT &p) const {return PT(x-p.x,y-p.y);}
        PT operator * (double c) const { return PT(x*c, y *c);}
        PT operator / (double c) const { return PT(x/c, y /c);}
        double mag(){return sqrt(x*x+y*y);}
    };
    
    PT RotCCW(PT p,double ang) {return PT(p.x*cos(ang) - p.y*sin(ang) , p.x*sin(ang) + p.y * cos(ang));}
    #define PI 0.01745329251994329914588889
    
    int main()
    {
        int T;
        cin>>T;
        while(T--) {
            int n;
            cin >> n;
            PT pivot = PT(0,0) , dir = PT(1,0);
            double d;
            char cmd[11];
            for(int i = 0;  i < n ; i ++ ) {
                scanf("%s %lf",cmd, &d);
                if(strcmp(cmd,"fd")== 0) pivot = pivot + dir * d;
                if(strcmp(cmd,"bk")== 0) pivot = pivot - dir * d;
                if(strcmp(cmd,"lt")== 0)  d = PI * d , dir =  RotCCW(dir,d);
                if(strcmp(cmd,"rt")== 0)  d = PI * d , dir = RotCCW(dir,  - d) ;
            }
            printf("%d\n",(int) (pivot.mag() + .5) );
        }
    }
    

    Uva 11506

    Link:11506 – Angry Programmer

    Solution:
    This problem is a classical problem known as minimum cut of a graph.
    We have to split the graph into two part such that node 1 remains in one part, and node n remains in other.
    This problem is dual of finding maximum flow of a graph.
    For details read : Maxflow

    Graph Contruction:
    We split each vertex into two nodes.(vin – vout)
    for each node other than 1 and n, we give an edge vin to vout with capacity c[i] (cost of destroying i th machine)
    for each edge (u,v,w) :
    if(u==1 || v ==1 ) then we add (1 -> other node ) with capacity w
    else : (uout -> vin ) with capacity w, (vout -> uin) with capacity w, as edges are bidirectional.

    Now run standard max-flow algorithm for find max-flow. And ans = maxflow of the graph.

    Click to See Code
    #include <bits/stdc++.h>
    using namespace std;
    const int N = 3000;
    const int INF = 1e9;
    typedef int T;
    struct Edge
    {
        int u, v;
        T cap, flow;
        Edge(int u, int v, T c, T f):u(u), v(v), cap(c), flow(f) {}
    };
    
    struct Dinic
    {
        int n, m, s, t;
        const T oo = 1e9;
        vector<Edge> edge;
        vector<int> G[N];
        bool vis[N];
        int d[N];
        int cur[N];
        
        void init(int n)
        {
            this->n=n;
            for(int i=0; i<=n; i++)
                G[i].clear();
            edge.clear();
        }
        
        void addEdge(int u, int v, T cap)
        {
            edge.push_back(Edge(u, v, cap, 0));
            edge.push_back(Edge(v, u, 0, 0));
            m=edge.size();
            G[u].push_back(m-2);
            G[v].push_back(m-1);
        }
        
        bool bfs()
        {
            memset(vis, 0, sizeof vis);
            queue<int> q;
            q.push(s);
            d[s]=0;
            vis[s]=1;
            while(!q.empty())
            {
                int x=q.front();
                q.pop();
                for(int i=0; i<G[x].size(); i++)
                {
                    Edge& e=edge[G[x][i]];
                    if(!vis[e.v] && e.cap>e.flow)
                    {
                        vis[e.v]=true;
                        d[e.v]=d[x]+1;
                        q.push(e.v);
                    }
                }
            }
            return vis[t];
        }
        
        T dfs(int x, T a)
        {
            if(x==t || a==0)return a;
            T flow=0, f;
            for(int& i=cur[x]; i<G[x].size(); i++)
            {
                Edge& e=edge[G[x][i]];
                if(d[x]+1==d[e.v] && (f=dfs(e.v, min(a, e.cap-e.flow)))>0)
                {
                    e.flow+=f;
                    edge[G[x][i]^1].flow-=f;
                    flow+=f;
                    a-=f;
                    if(a==0)break;
                }
            }
            return flow;
        }
        
        T dinitz(int s, int t)
        {
            this->s=s;
            this->t=t;
            T flow=0;
            while(bfs())
            {
                memset(cur, 0, sizeof cur);
                flow+=dfs(s, oo);
            }
            return flow;
        }
    } maxf;
    int main()
    {
        int n,m;
        while(scanf("%d %d",&n,&m)==2) {
            if(n==0&&m==0) break;
            maxf.init(105);
            for(int i = 2; i < n ; i ++ ) {
                int id,c;
                scanf("%d %d",&id,&c);
                maxf.addEdge(id,id+n,c);
            }
            for(int i = 0; i < m; i ++ ){
                int u,v,w;
                scanf("%d %d %d",&u,&v,&w);
                if(min(u,v)==1) {
                    maxf.addEdge(1,max(u,v),w);
                }
                else {
                    maxf.addEdge(u+n,v,w);
                    maxf.addEdge(v+n,u,w);
                }
                
            }
            
            int ans = maxf.dinitz(1,n);
            printf("%d\n",ans);
        }
        
    }
    

    Uva 11508

    Link : Uva 11508
    Idea: Adhoc
    n = count of number
    If maximum number in the input < n, there is a solution, else not .The solution is generated by following means.
    Each unique number is assigned to pos i, that is if there is a c then array[c] = c, The rest of numbers can be randomly inserted in any position.

    Click to See Code
    #include <bits/stdc++.h>
    using namespace std;
    
    string str;
    int main()
    {
        while(getline(cin,str)) {
            int a;
            istringstream iss(str);
            int iM = -1;
            int cnt = 0;
            multiset<int> Pos,v;
            while(iss >> a) {
                iM = max(iM, a);
                cnt ++;
                v.insert(a);
            }
            if(iM < cnt ) {
                for(int i = 0; i < cnt; i ++ ) Pos.insert(i);
                map<int,int> ar;
                for(int i = 0; i < cnt ; i ++ ) {
                    if(v.count(i)) {
                        v.erase(v.find(i));
                        Pos.erase(i);
                        ar[i] = i;
                    }
                }
                for(auto a : v ) {
                    ar[*Pos.begin()] = a ;
                    Pos.erase(Pos.begin());
                }
                int f = 0;
                for(auto a : ar) {
                    if(f) printf(" ");
                    printf("%d",a.second);
                    f = 1;
                }
                printf("\n");
                
            }
            else {
                printf("Message hacked by the Martians!!!\n");
            }
            
        }
    }
    

    Uva 11509

    Link: Uva 11509
    Idea: Simple Angle calculation.
    Given two vector. We can calculate the angle between them,
    Let P = x i + y j  , Q = u i + w j
    where i = unit vector in +x axis, j = unit vector in +y axis
    The angle between them = acos (dot(P,Q) / |P| / |Q| )
    Now this angle is 0 <= x < PI. This returns the smallest angle between P and Q . To consider only CCW movement, We need to check if Q is in right rotate or left rotate in respect of P.
    If Left Rotate : Then we just add angle
    If Right Rotate : Then we add 2*PI – angle

    After summing all the rotations , to calculate turn we divide sum by 2*PI.

    Click to See Code
    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1<<20;
    struct PT {
        double  x,y;
        PT(double x=0, double y=0) : x(x), y(y) {}
        PT(const PT &p) : x(p.x), y(p.y)    {}
        PT operator + (const PT &p) const { return PT(x+p.x , y + p.y);}
        PT operator - (const PT &p) const { return PT(x-p.x , y - p.y);}
        PT operator * (double c) const { return PT(x*c,y*c);}
        PT operator / (double c) const { return PT(x/c,y/c);}
        void input(){scanf("%lf %lf",&x,&y);}
    }p[N];
    
    double dot(PT p,PT q){ return p.x * q.x + p.y * q.y;}
    double cross(PT p,PT q) {return p.x*q.y - p.y*q.x;}
    double dist2(PT p,PT q) {return dot(p-q , p-q);}
    double DIM(PT p) {return sqrt(p.x*p.x+p.y*p.y);}
    #define PI 3.1415926535897932
    #define EPS 1e-8
    double calc(PT a,PT b)
    {
        double c = cross(a,b);
        if(c >= 0){
            double oo = dot(a,b) / DIM(a) / DIM(b);
            if(oo>1) oo=1;
            else if(oo<-1) oo= -1;
            return acos(oo);
        }
        else {
            double oo = dot(a,b) / DIM(a) / DIM(b);
            if(oo>1) oo=1;
            else if(oo<-1) oo= -1;
            return 2*PI - acos(oo);
        }
    }
    int main()
    {
        int n;
        while(scanf("%d",&n)==1 && n) {
            for(int i = 0; i < n ; i ++) scanf("%lf %lf",&p[i].x, &p[i].y);
            double ang = 0;
            PT dir = p[1]-p[0];
            for(int i = 1; i < n ; i ++) {
                PT newdir = p[(i+1) %n] - p[i];
                ang += calc(dir, newdir);
                dir = newdir;
            }
            ang += calc(dir, p[1] - p[0]);
            printf("%.0lf\n", (ang / (2*PI)));
        }
    }
    
    

    Uva 11510

    Link : Uva 11510

    Idea : Mathematical Problem.
    Given
    \frac{4}{n} = \frac{1}{x} + \frac{1}{y} + \frac{1}{z}
    Now at least one of x , y , z is smaller then n. otherwise summation of them will never equal to 4 /n .(verify)
    Iterate through x = 1 … n
    \frac{4}{n} - \frac{1}{x} = \frac{P}{Q} =  \frac{1}{y} + \frac{1}{z}

    We need to represent \frac{P}{Q} = \frac{1}{y} + \frac{1}{z}

    Lemma : Suppose that n and d are relatively prime positive integers. 
    Then n/d is the sum of two unit fractions if and only 
    if there are positive integer divisors A and B of d such that A+B is divisible by n.
     
    

    Factorisation of Q :
    As Q <= n * x which can be 10^8 at most. We can factorise Q by iterating from 1 to sqrt(Q) and check.
    Another way : as Q is at most multiple of n * x . then if we calculate factors of x and factors of n , then The factors of Q
    is multiplication of each pair.
    Now A and B is factor of Q and A + B is divisible by P. then
    D = (A+B) / P;
    \frac{P}{Q} = \frac{1}{D*Q/A} + \frac{1}{D*Q/B}

    Click to See Code
    #include <bits/stdc++.h>
    using namespace std;
    vector<int>fac;
    
    const int N = 1e4+5;
    bool vis[N];
    vector<int> F[N];
    void seive()
    {
        for(int i = 2; i < N; i ++ ) {
            F[i].push_back(1);
            if(vis[i] == 0 ) {
                for(int j = i;  j < N; j += i)  F[j].push_back(i), vis[j] = 1;
            }
        }
    }
    
    int main()
    {
        seive();
        int n;
        while(scanf("%d",&n)==1 && n) {
            if(n%2==0) printf("%d %d %d\n",n,n,n/2);
            else {
                //printf("For = %d\n",n);
                for(int x = n; x >= 1 ; x -- ) {
                    int up = 4 * x - n;
                    int down = x * n;
                    if(up < 0) break;
                    int k = __gcd(up,down);
                    up = up / k , down /= k;
                    set<int>S;
                    vector<int>temp;
                    fac.clear();
                    for(auto a: F[x]) {
                        for(auto b : F[n]) {
                            S.insert(a*b);
                        }
                    }
                    for(auto a: S) if(down % a) temp.push_back(a);
                    for(auto a: temp)S.erase(a);
                    for(auto a: S) fac.push_back(a);
                    bool f = 1;
                    
                    for(int i = 0; i < fac.size() &&f; i ++ ) {
                        for(int j = i; j < fac.size() && f; j ++ ) {
                            if((fac[i] + fac[j] ) % up == 0) {
                                long long A = fac[i], B  = fac[j];
                                long long D = (A+B)/up;
                                printf("%d %lld %lld\n", x, D * down / A , D * down / B);
                                f = 0;
                                break;
                            }
                        }
                    }
                    
                    if(f==0) break;
                    
                }
                
            }
        }
    }
    

    Uva 11512

    Link: 11512 – GATTACA
    Solution: Suffix Array
    This is an easy problem that can be solved using suffix array.

    Build suffix array and LCP array
    Now, for each i th suffix in suffix array, we know that longest Common prefix of i th and i-1 th suffix is stored in LCP[i].
    So the substring starting at sa[i] of length LCP[i] has occurred in another place in the string( i-1 th suffix)

    For understanding:

    Let S=GAGAGAG
    I append a dummy end. 
    S =    G A G A G A G #
    index= 0 1 2 3 4 5 6 7
    Suffix Array:      LCP Array
    7 	#		0
    5	AG#		0
    3	AGAG#		2
    1	AGAGAG#		4
    6	G#		0
    4	GAG#		1
    2	GAGAG#		3
    0	GAGAGAG#	5
    

    Take the maximum of LCP array. What this maximum value means? Here maximum value = 5
    Ans : This means, A substring of length 5 has occurred at least twice in between suffix(2) and suffix 0
    So this is the longest substring that occurs at least twice.

    How to determine the string ?
    Ans: Go from the suffix array and stop at the first suffix which has LCP[i] = maximum_value, The substring starting from sa[i] of length maximum value is the answer and the occurance of the substring can be found by iterating the suffix array until the LCP < maximum_value
    In our example: index = 0, and maximum_value = 5

    For details see my implementation:

    Click to See Code
    #include<bits/stdc++.h>
    using namespace std;
    
    
    const int N = 1005;
    char s[N];
    int wa[N],wb[N],wv[N],wc[N];
    int r[N],sa[N],rak[N], height[N],dp[N][22], SIGMA = 0 , n;
    
    int cmp(int *r,int a,int b,int l){return r[a] == r[b] && r[a+l] == r[b+l];}
    void da(int *r,int *sa,int n,int m)
    {
        int i,j,p,*x=wa,*y=wb,*t;
        for( i=0;i<m;i++) wc[i]=0;
        for( i=0;i<n;i++) wc[x[i]=r[i]] ++;
        for( i=1;i<m;i++) wc[i] += wc[i-1];
        for( i= n-1;i>=0;i--)sa[--wc[x[i]]] = i;
        for( j= 1,p=1;p<n;j*=2,m=p){
            for(p=0,i=n-j;i<n;i++)y[p++] = i;
            for(i=0;i<n;i++)if(sa[i] >= j) y[p++] = sa[i] - j;
            for(i=0;i<n;i++)wv[i] = x[y[i]];
            for(i=0;i<m;i++) wc[i] = 0;
            for(i=0;i<n;i++) wc[wv[i]] ++;
            for(i=1;i<m;i++) wc[i] += wc[i-1];
            for(i=n-1;i>=0;i--) sa[--wc[wv[i]]] = y[i];
            for(t=x,x=y,y=t,p=1,x[sa[0]] = 0,i=1;i<n;i++) x[sa[i]]= cmp(y,sa[i-1],sa[i],j) ? p-1:p++;
        }
    }
    void calheight(int *r,int *sa,int n)
    {
        int i,j,k=0;
        for(i=1;i<=n;i++) rak[sa[i]] = i;
        for(i=0;i<n;height[rak[i++]] = k ) {
            for(k?k--:0, j=sa[rak[i]-1] ; r[i+k] == r[j+k] ; k ++) ;
        }
    }
    
    
    char str[1005];
    int idx[150];
    int main()
    {
        idx['A'] = 1,idx['C'] = 2,idx['T'] = 4, idx['G'] = 3;
        int t;
        scanf("%d",&t);
        while(t--) {
            scanf("%s",str);
            for(int i= 0 ; str[i]; i++ )r[i] = idx[str[i]];
            int n = strlen(str);
            r[n] = 0;
            da(r,sa,n+1,7);
            calheight(r,sa,n);
            int ans = 0;
            for(int i = 1; i <= n; i ++ ) {
                int k = height[i];
                ans = max(ans,k);
            }
            if(ans == 0) {
                printf("No repetitions found!\n");
                continue;
            }
            for(int i = 1; i <= n; i ++ ) {
                if(height[i]==ans) {// Found the answer.
                    int end = i;
                    for(int j = i+1; j <= n; j ++ ) {
                        if(height[j] >= ans) {// calculating the number of occurrences
                            end = j;
                        }
                        else break;
                    }
                    for(int j = 0; j < ans; j ++ ){
                        printf("%c",str[sa[i] + j]);
                    }
                    printf(" %d\n",end - i + 2);
                    break;
                }
            }
        }
    }
    

    Uva 11513

    Link : 11513 – 9 Puzzle
    Idea: BFS
    Each configuration denotes a node in the graph. We have initial configuration starting from {1,2,3,4,5,6,7,8,9}. Run bfs and calculate the distance from the Starting node.
    For Horizontal Rotate ,We left rotate (reverse in direction )
    For Vertical Rotate, We move down opposite to real move.
    To find the path, We keep a nodes parent and by which move We have gone u->v.
    Traversing node until initial, get the path

    Click to See Code
    #include <bits/stdc++.h>
    using namespace std;
    
    map<string,int> Map;
    map<int,string> RevMap;
    map<int,int> dp;
    int a[3][3];
    int cnt  = 0;
    string encode(int a[][3])
    {
        string s;
        for(int i = 0; i < 3; i ++) {
            for(int j = 0; j < 3; j ++ ) s.push_back(a[i][j] + '0');
        }
        return s;
    }
    void decode(int u,int a[][3])
    {
        string s = RevMap[u];
        for(int i = 0, k = 0; i < 3; i ++ )
            for(int j = 0; j < 3; j ++ ){
                a[i][j] = s[k] - '0';
                k++;
            }
        return;
    }
    
    
    int get(string s)
    {
        if(Map.count(s)) return Map[s];
        Map[s] = ++cnt;
        RevMap[cnt] = s;
        return cnt;
    }
    
    void HR(int a[][3], int row, int b[][3])
    {
        for(int i=0;i<3;i++)for(int j=0;j<3;j++)b[i][j]=a[i][j];
        for(int j = 1; j < 3; j ++ ) b[row][j-1]= a[row][j];
        b[row][2] = a[row][0];
    }
    
    void VR(int a[][3], int col, int b[][3])
    {
        for(int i=0;i<3;i++)for(int j=0;j<3;j++)b[i][j]=a[i][j];
        for(int i = 1; i < 3; i ++) b[i][col] = a[i-1][col];
        b[0][col] = a[2][col];
    }
    
    map<int,pair<int,int> > Par;
    map<int,int> F;
    void solve()
    {
        string s = encode(a);
        int u = get(s);
        queue<int>q;
        q.push(u);
        dp[u] = 0;
        int b[3][3];
        while(!q.empty()){
            int u = q.front(); q.pop();
            decode(u,a);
            for(int i = 0; i < 3; i ++ ) {
                HR(a,i,b);
                string vs = encode(b);
                int v = get(vs);
                if(dp.count(v) == 0 || dp[v] > dp[u] + 1 ) {
                    dp[v] = 1 + dp[u];
                    Par[v] = make_pair(0,i);
                    q.push(v);
                    F[v] = u;
                }
            }
            for(int i = 0; i < 3; i ++ ) {
                VR(a,i,b);
                string vs = encode(b);
                int v = get(vs);
                if(dp.count(v) == 0 || dp[v] > dp[u] + 1 ) {
                    dp[v] = 1 + dp[u];
                    Par[v] = make_pair(1,i);
                    F[v] = u;
                    q.push(v);
                }
            }
            
        }
    }
    int main()
    {
        int o = 1;
        for(int i = 0; i < 3; i ++) for(int j = 0; j < 3; j ++ ) a[i][j] = o , o++;
        solve();
        int n;
        while(scanf("%d",&n) == 1 && n) {
            a[0][0] = n;
            scanf("%d %d",&a[0][1], &a[0][2]);
            for(int i = 1; i < 3;i ++ )for(int j= 0;j<3;j++) scanf("%d",&a[i][j]);
            
            string s = encode(a);
            if(Map.count(s)) {
                int u = Map[s];
                vector<pair<int,int> > path;
                while(u != 1) {
                    path.push_back(Par[u]);
                    u = F[u];
                }
                printf("%d ", (int)path.size());
                for(int i = 0; i < path.size(); i ++ ) {
                    printf("%c%d",path[i].first==0 ? 'H' :'V', path[i].second +1);
                }
                printf("\n");
            }
            else printf("Not solvable\n");
            
        }
    }
    
    

    Uva 11514

    Link : 11514 – Batman
    Idea: Dynamic Programming
    Let’s assume we are to determine minimum power needed to destroy all the villans. As the power and vilan are to be faced according to list,We can keep each state by (index of the power, index of villan), indexing from 0
    dp[i][j] = minimum power needed to destroy all villan from [j..v-1] using power only [i..p-1]
    Two case:
    * if the i th power can be used against j th villan , then cost1 = damage[i] + dp[i+1][j+1];
    * cost2 = dp[i+1][j] // Not using
    After that ,We can check if mincost <= power of batman

    Click to See Code
    #include <bits/stdc++.h>
    using namespace std;
    int p,v,e;
    const int N = 1005;
    char name[N][105], vl[N][105];
    int at[N], dmg[N];
    int def[N];
    char l[1000005];
    map<string,int> Map;
    int Mat[N][N];
    long long dp[N][N];
    
    long long F(int p1, int p2)
    {
        if(p1 == p ) {
            if( p2 == v) return 0;
            else return 1e15;
        }
        if(dp[p1][p2] !=-1 )return dp[p1][p2];
        long long res = 1e15;
        if(Mat[p1][p2] && at[p1] >= def[p2]) res = dmg[p1]  + F(p1+1, p2+1);
        res = min(res, F(p1+1,p2));
        return dp[p1][p2] = res;
    }
    
    int main()
    {
        while(scanf("%d %d %d",&p,&v,&e)==3) {
            if(p==0 &&v == 0 && e == 0) break;
            memset(Mat,0,sizeof Mat);
            for(int i = 0;i < p; i ++) {
                scanf("%s %d %d",name[i] ,  &at[i] , & dmg[i]);
                Map[name[i]] = i;
            }
            for(int i = 0; i < v; i ++ ){
                scanf("%s %d %s", vl[i] ,  &def[i] , l);
                for(int i=0; l[i];i++) if(l[i]==',' )l[i]=' ';
                istringstream iss (l);
                string o;
                while(iss >> o ) {
                    Mat[Map[o]][i] = 1;
                }
            }
            memset(dp,-1,sizeof dp);
            long long p = F(0,0);
            if(p <= e) printf("Yes");
            else printf("No");
            puts("");
            Map.clear();
                                          
        }
    }
    

    Uva 11515

    Idea: Brute Force
    As the number of crane <= 15, So we can check every subset of the cranes and check if any intersection present in that subset and then Output the maximum value.
    Intersection is Checked by following method:

    if (distance(circle1, circle2) <= (r1 + r2) ) return INTERSECT;
    return NOT_INTERSECT;
    
    Click to See Code
     
     #include <bits/stdc++.h>
    using namespace std;
    const int N = 15;
    int x[N],y[N],r[N];
    
    bool iN(int i,int j)
    {
        long long dx = x[i] - x[j], dy = y[i] - y[j];
        if(dx*dx + dy*dy <= (r[i] + r[j]) * (r[i] + r[j])) return 1;
        return 0;
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--) {
            int n;
            scanf("%d",&n);
            for(int i = 0; i < n ;i ++) scanf("%d %d %d",&x[i],&y[i], &r[i]);
            long long ans = 0;
            for(int i = 0; i < 1 << n; i ++ ) {
                vector<int>v;
                long long can = 0;
                for(int j = 0; j < n ; j ++ ) {
                    if(i&1<<j) {
                        v.push_back(j);
                        can += r[j] * r[j];
                    }
                }
                bool flag= 1;
                for(int j = 0; j < v.size() ; j ++ ) {
                    for(int k = j + 1; k < v.size(); k ++ ) {
                        if(iN(v[j],v[k])){
                            flag = 0;
                            break;
                        }
                    }
                }
                if(flag) ans = max(ans, can);
            }
            printf("%lld\n",ans);
        }
    }
    

    Uva 11516

    Link : 11516 – WiFi

    Solution: Binary Search + Greedy
    First assume the answer, that is the maximum distance between any house. Then try to cover all the houses using n access points. Follow the binary search rules and that will give you AC.

    For greedy: The first access point is placed in ( first person house co-ordinate + ans / 2 ) co-ordinate. Because, The left of first person’s house is no necessary to us. Similarly put all the other access points.

    Click to See Code
    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1e5+5;
    
    int x[N];
    int n,m;
    
    bool can(int M) // Try to place the access points
    {
        int prv = -1e8 , cnt = 0;
        for(int i= 0; i < m ;i ++ ) {
            if(x[i] - prv > M) {
                cnt ++;
                prv = x[i];
            }
        }
        return cnt <= n;
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--) {
            scanf("%d %d",&n,&m);
            for(int i = 0; i < m ;i ++ ) scanf("%d",&x[i]);
            sort(x,x+m);
            int low = 0, high = 1e6+6 , mid , ans = 0;
            while(low <= high) {
                mid = (low + high) / 2;
                if(can(mid)) {
                    ans = mid;
                    high = mid-1;
                }else low = mid+1;
            }
            printf("%.1lf\n" , ans * 1./ 2);
        }
    }
    

    Uva 11517 – Exact Change

    Link: 11517 – Exact Change

    Idea: DP
    Classical coin change dp.
    First assume ans = 20000. (Because the denominator are 10000 at most).
    Try to find the minimum coin needed to make i cents. Then find the answer.

    Click to See Code
    #include <bits/stdc++.h>
    using namespace std;
    int coin[105];
    int dp[20005];
    int main()
    {
        int t,n,sum;
        scanf("%d",&t);
        
        while(t--){
            scanf("%d",&sum);
            scanf("%d",&n);
            for(int i = 0; i < n; i ++ )scanf("%d",&coin[i]);
            memset(dp,-1,sizeof dp);
            int N = 20005-1;
            dp[0] = 0;
            for(int i = 0; i < n ;i ++) {
                for(int j = N; j >= coin[i] ; j--) {
                    if(dp[j-coin[i]] !=-1) {
                        if(dp[j]==-1) dp[j] = 1 + dp[j-coin[i]];
                        else dp[j] = min(dp[j], 1 + dp[j-coin[i]]);
                        if(j >= sum ) N = min(N,j);
                    }
                }
            }
            printf("%d %d\n",N,dp[N]);
        }
    }
    

    Uva 11518 – Dominos 2

    Link : Uva 11518 – Dominos 2

    Idea: DFS
    For each starting point,Run a dfs . and mark the visited node.
    At the end, output the # of visited nodes.

    Click to See Code
    
    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 1e4+1;
    vector<int>G[N];
    bitset<N>B;
    bool vis[N];
    void dfs(int u)
    {
        if(vis[u]) return;
        B[u] = 1;
        vis[u] = 1;
        for(int i = 0; i < G[u].size(); i ++ ) {
            int v = G[u][i];
            dfs(v);
        }
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--) {
            int n,m,l;
            scanf("%d %d %d",&n,&m,&l);
            for(int i = 0; i < m ; i ++) {
                int a,b;
                scanf("%d %d",&a,&b);
                G[a].push_back(b);
            }
            memset(vis,0,sizeof vis);
            B.reset();
            for(int i = 0; i < l ; i ++ ) {
                int p;
                scanf("%d",&p);
                dfs(p);
            }
            printf("%ld\n",B.count());
            for(int i = 1;i <= n; i ++) G[i].clear();
        }
        
    }
    

    Uva 11519 – Logo 2

    Link: Uva 11519 – Logo 2

    Idea:

    Let's assume the starting position is (0,0).
    If the missing is "fd" or "bk"
    	We execute all the commands and lets finally we are at point P(x,y) and 
            while we are about to execute "fd" or "bk"
    	command, we have direction d;
    	so, for fd, 
    	we have P + d * L = 0, We can write this equation as
    	x + d_x * L =0, L = -x/d_x , considering x-part
    	Again for "bk"
    	We have P - d * L = 0
    	x - d_x * L = 0, L = x / d_x , considering only x-part
    
    	L is the final answer.
    if the missing command is type of "lt" or "rt":
    	as the answer is integer, so we try all possible angle in [0,360], and
            see if we can be back in the starting position.
    
    

    Only problem about solving this was EPS = 1e-2

    Click to See Code
    
    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 1005;
    string command[N];
    int value[N];
    
    struct PT {
        double x,y;
        PT(){}
        PT(double x,double y):x(x),y(y){}
        PT operator + (const PT &p) const {return PT(x+p.x,y+p.y);}
        PT operator - (const PT &p) const {return PT(x-p.x,y-p.y);}
        PT operator * (double c) const { return PT(x*c, y *c);}
        PT operator / (double c) const { return PT(x/c, y /c);}
        double mag(){return sqrt(x*x+y*y);}
    };
    PT RotCCW(PT p,double ang) {return PT(p.x*cos(ang) - p.y*sin(ang) , p.x*sin(ang) + p.y * cos(ang));}
    #define PI 0.01745329251994329914588889
    #define EPS 1e-2
    int n;
    PT F;
    
    PT calc(int par= -1)
    {
        PT pivot = PT(0,0) , dir = PT(1,0);
        for(int i = 0; i < n ; i ++ ) {
            if(i==par) {
                F= dir;
                continue;
            }
            string cmd = command[i];
            double d = value[i];
            if(cmd.compare("fd")== 0) pivot = pivot + dir * d;
            if(cmd.compare("bk")== 0) pivot = pivot - dir * d;
            if(cmd.compare("lt")== 0)  d = PI * d , dir =  RotCCW(dir,d);
            if(cmd.compare("rt")== 0)  d = PI * d , dir = RotCCW(dir,  - d) ;
        }
        return pivot;
    }
    
    
    int main()
    {
        int t,  id ;
        cin >> t;
        while(t-- ) {
            cin>> n;
            id = 0;
            for(int i = 0; i < n ; i ++ ) {
                string cmd,t;
                cin >> cmd >> t;
                if(t.compare("?") == 0)  {
                    id = i;
                    command[i] = cmd;
                }
                else {
                    command[i] = cmd;
                    value[i] = atoi(t.c_str());
                }
            }
            if(command[id].compare("fd") == 0 || command[id].compare("bk") == 0) {
                PT f = calc(id);
                int sig = (command[id].compare("fd") == 0 ? -1 : 1);
                printf("%.0lf\n", f.x / F.x *  sig + EPS );
            }
            else {
                for(int ang = 0; ang < 360; ang ++ ) {
                    value[id] = ang;
                    PT r = calc();
                    if(fabs(r.mag()) < EPS) {
                        printf("%d\n", ang);
                        break;
                    }
                }
            }
            
        }
    }
    
    
    

    Uva 11520 – Fill the Square

    Link: 11520 – Fill the Square

    Idea: Adhoc

    Iterate the grid into row major order.
    for each cell, 
         if it is empty:
               We try to put smallest letter so that its adjacent cells don't have this letter.
               Put the letter .
               As size of letter is 26, So in a cell ,we will never run out of option. Thats why greedy choice works.
         else do nothing
    Output the grid
    
    Click to See Code
    
    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 15;
    string grid[N];
    int n ;
    
    bool valid( int x, int y)
    {
        if( x < 0 || y < 0 || x >= n || y >= n ) return false;
        return true;
    }
    
    int dir[][2] = {{0,1},{0,-1},{-1,0},{1,0}};
    int main()
    {
        
        int tc ,cs = 0 ;
        scanf("%d",&tc);
        while (tc -- ) {
            scanf("%d",&n);
            for( int i = 0; i < n ; i ++ ) {
                cin >> grid[i];
            }
            
            for(int i =0 ; i < n ; i ++ ) {
                for (int j = 0 ; j < n ; j ++ ) {
                    if(grid[i][j] !='.') continue;
                    for( int p = 0 ; p < 26 ;p ++ ) {
                        bool flag = true;
                        for( int d = 0 ; d < 4 ; d ++ ) {
                            int x = i + dir[d][0];
                            int y = j + dir[d][1];
                            
                            if(valid(x,y) && grid[x][y] == p + 'A' ) {
                                flag = false;
                            }
                        }
                        
                        if( flag ) {
                            grid[i][j] = p +'A';
                            break;
                        }
                        
                    }
                }
            }
            
            printf("Case %d:\n" , ++cs) ;
            for( int i = 0 ;i < n ; i ++) {
                for ( int j = 0; j < n ; j ++ ) {
                    printf("%c",grid[i][j] );
                }
                printf("\n");
            }
            
        }
        
        return 0;
    }
    

    Uva 11522 – Pyramid Number

    Link :11522 – Pyramid Number

    Idea: Recursion + Observation

    Using Recursion , first generate some strictly pyramid numbers up to 150. You can see all the numbers greater than 77 is pyramid number. So you only need to generate [1,77] which are not pyramid numbers and this can be done using recursion.

    See my implementation for details

    Click to See Code
    
    #include <bits/stdc++.h>
    using namespace std;
    bool flag[101];
    const double EPS = 1e-8;
    bool dfs(int sum,int p,double fr)
    {
    
        if(fr> 1 + EPS || sum < 0) return 0;
        if(sum==0){
            if(fabs(fr-1) < EPS) return 1;
            return 0;
        }
        if(p>sum) return 0;
        return dfs(sum-p,p+1,fr + 1./p) || dfs(sum,p+1,fr);
    }
    int main()
    {
        memset(flag,1,sizeof flag);
        for(int i= 2; i <= 77; i ++ ) {// Checking pyramid numbers.
            if(dfs(i,2,0) == 0) {
                flag[i] = 0;
            }
        }
        int t,a,b;
        scanf("%d",&t);
        while(t--) {
            scanf("%d %d",&a,&b);
            if(a>b)swap(a,b);
            int cnt = 0;
            while(a<=77 && a<= b) {
                if(flag[a]) cnt++;
                a++;
            }
            cnt += b - a + 1;
            printf("%d\n",cnt);
        }
    }
    

    Uva 11523 – Recycling

    Idea : Dynamic Programming
    It is a standard Interval Dp problem.
    Since it is not allowed to move non-recyclable elements, we can take each maximal contiguous subsequence between non-recyclable materials and solve them independently using an dynamic programming. We need to minimise cost in interval (i,j) inclusive.

    First Map the strings into an interger and create an array. A series of same number is replaced by only one integer [1,2,2,2,1] => [1,2,1]
    For an interval, We have two case:

    * Pick only the ith element. In this case dp(i,j) = 1 + dp(i+1,j)
    * for each k in [i+1,j] :
    if array[i] = array[k] :
    We can pick ith element with k th element.
    dp(i,j) = min(dp(i,j) , dp(i+1,k) + dp(k+1,j));
    So for removing [i+1,k] segment, when we are about to pick the kth element ,
    We pick all the elements in interval [i+1,k-1] and pick ( ith and kth )
    element in a single move.
    Again the optimal cost for removing [k+1,j] interval.

    Try to think about this recursive relations. They never pop into mind easily.
    Simmilar Problem:

    1. Topcoder – MailArchiving
    2. Uva 11283

    Click to See Code
    #include <bits/stdc++.h>
    using namespace std;
    const int N = 105;
    map<string,int> Name;
    int cnt = 0;
    int val(string s)
    {
        if(Name.count(s)) return Name[s];
        Name[s] = ++cnt;
        return cnt;
    }
    int ar[N];
    int dp[N][N];
    int n;
    vector<int>v;
    int F(int i,int j)
    {
        if(i>j) return 0;
        
        if(i==j) {
            return 1;
        }
        if(dp[i][j] !=-1) return dp[i][j];
        int res = 1e5;
        res = F(i+1,j) + 1;
        for(int k = i+1; k <= j ; k ++ ) {
            if(v[k] == v[i]) {
                res = min(res , F(i+1,k) + F(k+1,j));
            }
        
        }
        return dp[i][j] =res;
    }
    int main()
    {
        
        int t,cs = 0;
        cin>>t;
        while(t--) {
            cin >> n;
            string s;
            cnt=0;
            for(int i = 0; i < n ;i ++ ) {
                cin >> s;
                if(islower(s[0])) {
                    ar[i] = val(s);
                }
                else {
                    ar[i] = 0;
                }
            }
            int prv = -1;
            v.clear();
            for(int i = 0; i < n ;i ++ ) {
                if(ar[i] != prv) {
                    v.push_back(ar[i]);
                    prv = ar[i];
                }
            }
            memset(dp,-1,sizeof dp);
            vector<int> R;
            R.push_back(-1);
            for(int i = 0; i < v.size();i ++ ) if(v[i] == 0) R.push_back(i);
            R.push_back(v.size());
            int ans = 0;
            for(int i = 0; i < R.size()-1; i ++ ) {
                ans += F(R[i]+1, R[i+1]-1);
            }
            printf("Case %d: %d\n",++cs, ans);
            Name.clear();
        }
    }
     
    

    Uva 11524 – InCircle

    Link : 11524 – InCircle

    Idea: Binary Search and Geometry
    First assume BP = x, Then We know AP from BP,
    Now AP = AR ( Proof ? )
    Then, We know CR from AR , Again, CQ = CR and calculate BQ from CQ

    The equation can be written as follows:

        double BP = x;
        double AP = m1*BP/n1;
        double AR = AP;
        double CR = m3 * AR / n3;
        double CQ = CR;
        double BQ = m2 * CQ / n2;
    

    Now we have length of each sides and can calculate the area of the triangle by herons formula.
    From trigonometry, We know radius of incircle of a triangle = Area/(s) where s = perimeter of triangle / 2
    So we check if this radius is smaller of larger than give r and work accordingly.

    Click to See Code
    #include <bits/stdc++.h>
    using namespace std;
    #define PI acos(-1.0)
    double r,m1,n1,m2,n2,m3,n3;
    
    
    double Tri(double a,double b,double c)
    {
        double s = (a+b+c)/2;
        if(a > s || b > s || c > s) return -1;
        return sqrt(s*(s-a)*(s-b)*(s-c));
    }
    
    double area;
    double calc(double mid)
    {
        double BP = mid;
        double AP = m1 *BP/n1;
        double AR = AP;
        double CR = m3 * AR / n3;
        double CQ = CR;
        double BQ = m2 * CQ / n2;
        area =  Tri(BQ + CQ , AR + CR, BP + AP);
        return 2 * area / (BQ + CQ + AR + CR + BP + AP);
    }
    
    int main()
    {
        int t;
        cin>>t;
        while(t--) {
            scanf("%lf %lf %lf %lf %lf %lf %lf",&r,&m1,&n1,&m2,&n2,&m3,&n3);
            
            double low = 0, high = 1e9 , mid , ans;
            for(int i = 0; i < 100 ; i ++ ) {
                mid = (low+high) / 2;
                double r2 = calc(mid);
                if(r2 < r) low = mid;
                else high = mid;
            }
            calc(low);
            printf("%.4lf\n",area);
        }
    }
    
    

    Uva 11525 – Permutation

    Link: 11525 – Permutation

    Idea: Binary Indexed Tree
    For each Si, We need to calculate what is the smallest integer in the current list which has Si numbers smaller in the list.
    For example:


    4
    1 2 1 0

    At first, We have {1,2,3,4}
    Now S1 = 1,What is the smallest number in the current list which has 1 number smaller than his ?
    Ans: 2.
    Because 1 is smaller than 2. So we output 2 and remove from the list.
    Now list = {1,3,4}

    S2 = 2 ,What is the smallest number in the current list which has 2 number smaller than his ?
    Ans: 4.
    1 and 3 are smaller than 4,
    List = {1,3}

    S3 = 1,What is the smallest number in the current list which has 1 number smaller than his ?
    Ans : 3
    List = {1}

    S4 = 0 ,
    Ans = 1

    We need an efficient data structure that solves our query and removal from the list. BIT is one of the solution. You can use SG tree also.

    For BIT , see here

    Click to See Code
    #include <bits/stdc++.h>
    using namespace std;
    
    int k;
    int M;
    int B[100005];
    void update(int x,int v)
    {
        while(x<=M) B[x] += v, x+=x&-x;
    }
    
    int bs(int x)
    {
        int r = 0, d = M;
        while(d && r < M) {
            int t = r + d;
            if( x >= B[t]) {
                x -= B[t];
                r = t;
            }
            d/=2;
        }
        return r+1;
    }
    int main()
    {
        int t,p;
        scanf("%d",&t);
        while(t--){
            scanf("%d",&k);
            memset(B,0,sizeof B);
            M = 1;
            while(M<=k) M*=2;
            for(int i = 1; i <= k; i ++ ) update(i,1);
            
            for(int i = 0; i < k; i ++ ) {
                scanf("%d",&p);
                int k = bs(p);
                update(k,-1);
                if(i)printf(" ");
                printf("%d",k);
            }
            puts("");
            
        }
    }
    

    Uva 11526 – H(n)

    Link : 11526 – H(n)

    Idea: Adhoc, Math
    We count from both ends.

    prev = n
    sum = 0;
    for each i = 1 to sqrt(n):
    	k = n/i,
    	so every number in range [k+1,prev] 
    		if we divide n by them, the output divident will be
    		same i-1.
    	sum += k + (prev - k) * (i-1);
    	prev= k
    
    

    To avoid over counting, I break the loop when k – i < 3

    Click to See Code
    #include <bits/stdc++.h>
    using namespace std;
    
    int main()
    {
        
        long long  n ,sum = 0 , prev, test  ;
        cin >> test;
        while (test -- ) {
            cin >> n;
            prev = n ;
            sum =  0 ;
            for (long long  i = 1; i * i <= n ; i ++) {
                long long    k = ( n / i );
                sum = sum + (prev - k ) * (i-1);
                sum += k ;
                prev  = k ;
                
                if( k - i < 3){
                    for (long long j = i + 1; j <= k ;  j ++) {
                        sum += n / j;
                    }
                    break;
                }
            }
            
            printf("%lld\n",sum);
        }
        return 0;
    }
    
    

    Another Solution from wiki :
    H(n) = 2 * (\sum_{i=1}^{\sqrt{n}} {n/i} ) - (\sqrt{n})^2

    This solution is rather easy.

    Click to See Code
    #include <bits/stdc++.h>
    using namespace std;
    
    
    int main()
    {
        
        long long  n ,sum = 0 , prev, test  ;
        cin >> test;
        while (test -- ) {
            cin >> n;
            int sqn = sqrt(n);
            long long sum = 0;
            for(int i = 1; i <= sqn; i++ ) {
                sum += n/i * 2;
            }
            printf("%lld\n",sum - sqn*sqn);
        }
        return 0;
    }
    
    


    Uva 11560 – Fixing the Bugs

    Link : Uva 11560
    Idea : DP, Greedy , Math
    Solution :

    The problem is bit difficult for my current level. So I searched over the net and found a good post how to solve this problem.
    Here is the Link : Solution

    Click to See Code
    #include <bits/stdc++.h>
    using namespace std;
    int b,t,CS = 1;
    double f;
    double p[12];
    int s[12];
    double dp[1<<10][105][105];
    int vis[1<<10][105][105];
    int fail[12];
    double calc(int Mask, int T, int F )
    {
        if(Mask+1 == (1<<b))return 0;
        if(T == 0 ) return 0;
        if(vis[Mask][T][F] == CS) return dp[Mask][T][F];
        
        int id = -1;
        double iM = -1e8;
        for(int i= 0;i < b; i++) {
            if(!(Mask & 1 << i)) {
                if(p[i] * s[i] > iM ) {
                    iM = p[i] * s[i];
                    id = i;
                }
            }
        }
        double res = p[id] * (s[id] + calc(Mask | 1 << id , T-1, F - fail[id]));
        double prv = p[id];
        p[id] *= f;
        fail[id] ++;
        res += (1- prv) * calc(Mask, T -1 , F + 1);
        p[id] = prv;
        fail[id] --;
                              
        vis[Mask][T][F]  = CS;
        return dp[Mask][T][F] = res ;
        
    }
    int main()
    {
        while(scanf("%d %d %lf",&b,&t,&f)==3) {
            for(int i = 0; i < b; i ++ ) scanf("%lf %d",&p[i],&s[i]);
            printf("%.9lf\n", calc(0,t,0));
            CS ++;
        }
        
    }
    
     
    

    Uva 11561 – Getting Gold

    Link : Uva 11561
    Idea : BFS, Graph
    solution: The square which is near to trap, we can visit it but can not go anywhere from that. This is main trick.

    Click to See Code
     
    #include <bits/stdc++.h>
    using namespace std;
    #define MP make_pair
    int r,c, x , y;
    char grid[55][55];
    bool vis[55][55], draft[55][55];
    int dir[][2] = {{0,1},{0,-1},{1,0},{-1,0}};
    bool ok(pair<int,int> a)
    {
        if(a.first >= 0 && a.first < r && a.second >= 0 && a.second < c && grid[a.first][a.second] != '#' && grid[a.first][a.second] != 'T') return 1;
        return 0;
    }
    void solve()
    {
        memset(draft,0,sizeof draft);
        for(int i = 0; i < r; i ++ ) {
            for(int j = 0; j < c; j ++)  {
                if(grid[i][j] == 'T') {
                    for(int k = 0; k < 4; k ++ ) {
                        int xp = i + dir[k][0];
                        int yp = j + dir[k][1];
                        if(ok(MP(xp,yp))) draft[xp][yp] = 1;
                    }
                }
            }
        }
        if(draft[x][y]) {printf("0\n");return;}
        memset(vis,0,sizeof vis);
        vis[x][y] =1;
        queue<pair<int,int> > q;
        q.push(MP(x,y));
        while(!q.empty()){
            auto a = q.front(); q.pop();
            for(int i = 0; i < 4; i ++ ) {
                auto b = MP(a.first + dir[i][0] , a.second + dir[i][1]);
                if(ok(b) && vis[b.first][b.second] == 0 ) {
                    vis[b.first] [b.second] = 1;
                    if(draft[b.first][b.second] == 0)q.push(b);
                }
            }
        }
        int cnt = 0;
        for(int i= 0;i < r; i ++)
            for(int j = 0; j < c; j ++ ) {
                if(vis[i][j] && grid[i][j] == 'G' ) cnt ++;
            }
        printf("%d\n",cnt);
    }
    int main()
    {
        while(scanf("%d %d",&c,&r)==2) {
            for(int i =0 ; i < r;i ++) scanf("%s", grid[i]);
            for(int i = 0; i < r;i ++) {
                for(int j = 0; j < c; j ++ ) {
                    if(grid[i][j] == 'P') {
                        x = i, y = j;
                        
                    }
                }
            }
            solve();
        }
        
    }
    /*
    7 4
    #######
    #P.GTG# 
    #..TGG# 
    #######
    8 6
    ########
    #...GTG# 
    #..PG.G# 
    #...G#G#
    #..TG.G#
    ########
    4 4
    ####
    #TP#
    #GG#
    ####
    */
    

    Pallindromic Tree Applications

    Category: Data Structure, String.

    Discussion:
    You should read this blog post before you go.

    I think you have finished reading this blog and understand basics of Pallindromic Tree.

    const int MAXN = 100005; // Length of the String
    typedef int T;          //
    struct Node{
        int nxt[26]; //In case alphabet is fixed,Change Accordingly
        int len, link;
        T val;
    };
    struct PalTree{
        Node node[MAXN]; // Node for each pallindrome
        char s[MAXN];   // String
        int go,sz;
    
        void init()     // Call this Before Any Computation
        {
            node[1].len= -1, node[1].link = 1;
            node[2].len = 0, node[2].link = 1;
            go = sz = 2;
        }
    
        bool add(int pos)
        {
            int ch = s[pos]-'a';
            int curlen=0,cur = go;
            while(true) {
                curlen = node[cur].len;
                if(pos-1-curlen >= 0 && s[pos-1-curlen] == s[pos]) break;
                cur=node[cur].link;
            }
            if(node[cur].nxt[ch]){
                go = node[cur].nxt[ch];         // Previously occurred Pallindrome, Here may need some computation
                return 0;
            }
            // Adding New Pallindrome
            sz++;
            go = sz;
            node[cur].nxt[ch] = go;
            node[go].len = 2 + node[cur].len;
    
            if(node[go].len == 1) {
                node[go].link = 2;              // First occurance of a letter, By definition a pallindrome
                return 1;
            }
    
            while(true) {
                cur = node[cur].link;
                curlen = node[cur].len;
                if(pos-1-curlen >= 0 && s[pos-1-curlen] == s[pos]) {
                    node[go].link = node[cur].nxt[ch];
                    break;
                }
            }
            node[go].link = node[cur].nxt[ch];  // Giving Suffix Link
                                                // May need some computation
            return 1;
    
        }
        void clear(){
            for(int i= 0;i <= sz ;i ++) memset(node[i].nxt,0,sizeof(node[i].nxt));
        }
    };
    

    Main ideas:

    init()

    Initialize pallindromic tree.
    node[1] -> is a pallindrome of -1 length to accept odd length pallindrome(“a”, “c”, “d” is accepted by this node, in other words single character pallindrome are accepted by this )
    node[2] -> is a pallindrome of 0 length to accept even length pallindrome (“aa”, “bb”,”abba” is accepted by this)

    add()

    add s[pos] to the pallindromic tree
    String s is 0 based.
    return : Is addition of s[pos] form a new pallindrome different from the previous ly present?
    return 1 is yes. 0 otherwise.

    clear()

    Clears Tree . Needed for multiple testcases

    Characteristics of Pallindromic Tree:

    # Every Node represents a pallindrome of the string except node[1] and node[2]. They are sentinel
    # Every Node has a suffix link to a pallindrome which corespondence to the pallindrome stricly smaller length and suffix of current node.
    # Time and space complexity is O(n)

    Now we see some applications.

    Longest Pallindrome

    This problem can be solved using manacher algorithm in O(n). Also solvable by binary search and hashing. But for our pallindromic tree,it is a basic operation, just iterate through all tree node and return the maximum
    My code link: longest Pallindromic Substring

    How many different Pallindrome

    Problem Link: Problem
    As the add() function returns whether any distinct pallindrome generated by adding s[pos]. So this is simply the sum of add()
    My code Link : How many different Pallindrome

    Number of Occurrences of Each Pallindrome

    Here the link becomes handy.Each node is storing the information occuring itself.
    S = “ababa”
    Now for each occurrences of a node, all the node upto root are reachable by using suffix link are also occurred. “ababa” -> “aba”->”a” . All gets updated one by one using topological order.
    So we add occurrences of each pallindrome to its suffix link. The nodes are created in topological order. So We just iterate from the end node to root and update suffix links.
    unnamed0
    Here is Practice Problem : How Many Occurrences
    My code: Number of Occurrences of Each Pallindrome

    Longest Common Pallindromic Substring

    Build one pallindromic tree for each string. Then dfs from root, As the blog post said we have two root, We need to do dfs from each root
    Here is a problem harder than discussed task. I think you will be able to understand.
    Problem Link : The Problem to Slow Down You
    My code: Problem to Slow Down You

    POJ – 3274

    Category : Hashing
    Solution :
    Will be explained later.

    /*
     *************************
     Id  : Matrix.code
     Task: POJ - 3274
     Date: 2016-02-10
    
     **************************
     */
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstdlib>
    #include <cstring>
    #include <vector>
    #include <map>
    using namespace std;
    
    /*------- Constants---- */
    
    #define Long                    long long
    #define ull                     unsigned long long
    #define mod                     1000000007
    #define MEMSET_INF              63
    #define MEM_VAL                 1061109567
    #define forn(i,n)               for( int i=0 ; i < n ; i++ )
    #define mp(i,j)                 make_pair(i,j)
    #define lop(i,a,b)              for( int i = (a) ; i < (b) ; i++)
    #define pb(a)                   push_back((a))
    #define SZ(a)                   (int) a.size()
    #define all(x)                  (x).begin(),(x).end()
    #define gc                      getchar_unlocked
    #define PI                      acos(-1.0)
    #define INF                     1<<29
    #define EPS                     1e-9
    #define Fr                      first
    #define Sc                      second
    #define Sz                      size()
    #define lc                      ((n)<<1)
    #define rc                      ((n)<<1|1)
    #define db(x)                   cout << #x << " -> " << x << endl;
    #define Di(n)                   int n;si(n)
    #define Dii(a,b)                int a,b;si(a);si(b)
    #define Diii(a,b,c)             int a,b,c;si(a);si(b);si(c)
    #define Si(n)                   si(n)
    #define Sii(a,b)                si(a);si(b)
    #define Siii(a,b,c)             si(a);si(b);si(c)
    #define min(a,b)                ((a)>(b) ? (b) : (a) )
    #define max(a,b)                ((a)>(b) ? (a):(b))
    /*---- short Cuts ------- */
    #define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
    typedef pair<int, int> ii;
    typedef vector<int > vi ;
    typedef vector<Long> vl;
    /*------ template functions ------ */
    #ifndef getchar_unlocked
    #define getchar_unlocked getchar
    #endif
    template<class T> inline void si(T &x)
    {
        register int c = gc();
        x = 0;
        int neg = 0;
        for(; ((c<48 | c>57) && c != '-'); c = gc());
        if(c=='-')
        {
            neg=1;
            c=gc();
        }
        for(; c>47 && c<58; c = gc())
        {
            x = (x<<1) + (x<<3) + c - 48;
        }
        if(neg) x=-x;
    }
    Long bigmod(Long p,Long e,Long M)
    {
        Long ret = 1;
        for(; e > 0; e >>= 1)
        {
            if(e & 1) ret = (ret * p) % M;
            p = (p * p) % M;
        }
        return ret;
    }
    Long gcd(Long a,Long b)
    {
        if(b==0)return a;
        return gcd(b,a%b);
    }
    Long modinverse(Long a,Long M)
    {
        return bigmod(a,M-2,M);
    }
    void io()
    {
        freopen("/Users/MyMac/Desktop/in.txt","r",stdin);
    }
    
    /*************************** END OF TEMPLATE ****************************/
    
    const int N = 100005;
    int a[N];
    int pf[31][N];
    map<pair<Long,Long> ,int>Map;
    int n,k;
    Long MOD1 = 1e9+7;
    Long MOD2 = 1e9+9;
    Long base = 31;
    Long base2= 37;
    pair<Long,Long> H(int a[],int k)
    {
        Long ret1 = 0, ret2 = 0;
    
        for(int i= 0; i < k - 1 ; i ++ ) {
                ret1 = ret1 * base + a[i];
                ret2 = ret2 * base2 + a[i];
                ret1 %=MOD1;
                ret2 %= MOD2;
        }
    
        return mp(ret1,ret2);
    }
    
    int main()
    {
    
          //freopen("in.txt","r",stdin);
    
        scanf("%d %d ",&n,&k);
        for(int i= 1; i <= n; i ++ )
        {
            scanf("%d",&a[i]);
        }
        if(k==1)
        {
            printf("%d\n",n);
            return 0;
        }
        for(int i= 1; i <= n; i ++ )
        {
            for(int j = 0 ; j < k ; j ++ )
            {
                if(a[i] & (1<<j))
                {
                    pf[j][i] = pf[j][i-1] + 1;
                }
                else pf[j][i] = pf[j][i-1];
            }
        }
        int iM = 0;
        int t[35];
        Map[mp(0,0)] = 0;
        for(int i= 1; i <= n; i ++ )
        {
            for(int j = 1; j < k ; j ++ )
            {
                t[j-1] = pf[j][i]- pf[j-1][i];
    
            }
    
            pair<Long,Long> k1 = H(t,k);
    
            if(Map.count(k1))
            {
                iM = max(iM, i - Map[k1]);
            }
            else Map[k1] = i;
        }
        cout << iM << endl;
    }
    
    

    HDU – 3032

    Category : Game Theory
    Link : Problem

    Solution :
    The problem requires knowledge about nim game and Sprague–Grundy theorem. If you don’t know this, then game : topcoder
    can help.

    So proceed to solution, As each heap is independent, So this game is combination of games, and there we can apply grundy number.
    We will find grundy number for each heap. If there are n heap, we calculate grundy number of each heap and xor them. If xorsum NONZERO, first one wins, othewise second person to move wins.

    The only problem is to find grundy number of each pile.

    Starting with 0 : grundy number gr(0) = 0, because it is a losing position.

    When p = 1
    we can move to only one position (0) , as 0 has grundy value of 0, then gr(1) = 1;

    1

    When p = 2
    we can move to 0, 1, (1,1)(Spliting into 2 heap).

    2
    So

    gr(2) = 2

    When p = 3 we can move to 0, 1, 2,(1,2)(Spliting into 2 heap).

    3
    Here grundy value of the state (1,2) = 3 because gr(1) ^ gr(2) = 1 ^ 2 = 3;
    so

    gr(3) = 4

    When p = 4

    4
    Here

    gr(4) = 3

    If we try like this we will find a pattern and this is

          if(n==0) return 0;
          if(n%4==1 || n%4 == 2) return n ;
          if(n%4 == 3) return n + 1;
          if(n%4 == 0) return n - 1;
    

    So the solution is now obvious.

    My code :

    /*
     *************************
     Id  : Matrix.code
     Task: HDU - 3032
     Date: 2016-02-10
    
     **************************
     */
    
    
    #include <bits/stdc++.h>
    using namespace std;
    
    #include<ext/pb_ds/assoc_container.hpp>
    #include<ext/pb_ds/tree_policy.hpp>
    using namespace __gnu_pbds;
    template <typename T>
    using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
    
    
    /*------- Constants---- */
    
    #define Long                    long long
    #define ull                     unsigned long long
    #define mod                     1000000007
    #define MEMSET_INF              63
    #define MEM_VAL                 1061109567
    #define forn(i,n)               for( int i=0 ; i < n ; i++ )
    #define mp(i,j)                 make_pair(i,j)
    #define lop(i,a,b)              for( int i = (a) ; i < (b) ; i++)
    #define pb(a)                   push_back((a))
    #define SZ(a)                   (int) a.size()
    #define all(x)                  (x).begin(),(x).end()
    #define gc                      getchar_unlocked
    #define PI                      acos(-1.0)
    #define INF                     1<<29
    #define EPS                     1e-9
    #define Fr                      first
    #define Sc                      second
    #define Sz                      size()
    #define lc                      ((n)<<1)
    #define rc                      ((n)<<1|1)
    #define db(x)                   cout << #x << " -> " << x << endl;
    #define Di(n)                   int n;si(n)
    #define Dii(a,b)                int a,b;si(a);si(b)
    #define Diii(a,b,c)             int a,b,c;si(a);si(b);si(c)
    #define Si(n)                   si(n)
    #define Sii(a,b)                si(a);si(b)
    #define Siii(a,b,c)             si(a);si(b);si(c)
    #define min(a,b)                ((a)>(b) ? (b) : (a) )
    #define max(a,b)                ((a)>(b) ? (a):(b))
    /*---- short Cuts ------- */
    #define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
    typedef pair<int, int> ii;
    typedef vector<int > vi ;
    typedef vector<Long> vl;
    /*------ template functions ------ */
    #ifndef getchar_unlocked
    #define getchar_unlocked getchar
    #endif
    template<class T> inline void si(T &x){register int c = gc();x = 0;int neg = 0;for(;((c<48 | c>57) && c != '-');c = gc());
          if(c=='-') {neg=1;c=gc();}for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}if(neg) x=-x;}
    Long bigmod(Long p,Long e,Long M){Long ret = 1;for(; e > 0; e >>= 1){if(e & 1) ret = (ret * p) % M;p = (p * p) % M;} return ret;}
    Long gcd(Long a,Long b){if(b==0)return a;return gcd(b,a%b);}
    Long modinverse(Long a,Long M){return bigmod(a,M-2,M);}
    void io(){freopen("/Users/MyMac/Desktop/in.txt","r",stdin);}
    
    /*************************** END OF TEMPLATE ****************************/
    
    const int N = 1001;
    
    int gr(int n)
    {
          if(n==0) return 0;
          if(n%4==1 || n%4 == 2) return n ;
          if(n%4 == 3) return n + 1;
          if(n%4 == 0) return n - 1;
    }
    
    
    int main()
    {
          //freopen("in.txt","r",stdin);
          Di(t);
          while(t--) {
                Di(n);
                int ans = 0;
                for(int i = 0;i  < n; i ++ ) {
                      Di(a);
                      ans ^= gr(a);
                }
                printf("%s\n", ans ? "Alice" : "Bob");
          }
          return 0;
    
    }
    
    

    Longest Common Substring of different string

    Sample Problem : Life Forms

    Category : Suffix – array
    Solution :

      First copy the string into a new integer array and place a value between them which will never occur in the strings.
      build suffix array and heigth (LCP) array
      Binary search on the length. Find if it is possible to get a substring which have length = mid and occur in > half of the number of string.
      Print the string.

    Now code :

    
    /*
    
     *************************
     Id  : Matrix.code
     Task: 11107 Life Forms
     Date: 2016-01-17
    
     **************************
    
     */
    
    #include <bits/stdc++.h>
    using namespace std;
    
    /*------- Constants---- */
    
    #define Long                    long long
    #define ull                     unsigned long long
    #define mod                     1000000007
    #define MEMSET_INF              63
    #define MEM_VAL                 1061109567
    #define forn(i,n)               for( int i=0 ; i < n ; i++ )
    #define mp(i,j)                 make_pair(i,j)
    #define lop(i,a,b)              for( int i = (a) ; i < (b) ; i++)
    #define pb(a)                   push_back((a))
    #define SZ(a)                   (int) a.size()
    #define all(x)                  (x).begin(),(x).end()
    #define gc                      getchar_unlocked
    #define PI                      acos(-1.0)
    #define INF                     1<<29
    #define EPS                     1e-9
    #define Fr                      first
    #define Sc                      second
    #define Sz                      size()
    #define lc                      ((n)<<1)
    #define rc                      ((n)<<1|1)
    #define db(x)                   cout << #x << " -> " << x << endl;
    #define Di(n)                   int n;si(n)
    #define Dii(a,b)                int a,b;si(a);si(b)
    #define Diii(a,b,c)             int a,b,c;si(a);si(b);si(c)
    #define Si(n)                   si(n)
    #define Sii(a,b)                si(a);si(b)
    #define Siii(a,b,c)             si(a);si(b);si(c)
    #define min(a,b)                ((a)>(b) ? (b) : (a) )
    #define max(a,b)                ((a)>(b) ? (a):(b))
    /*---- short Cuts ------- */
    #define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
    typedef pair<int, int> ii;
    typedef vector<int > vi ;
    typedef vector<Long> vl;
    /*------ template functions ------ */
    #ifndef getchar_unlocked
    #define getchar_unlocked getchar
    #endif
    template<class T> inline void si(T &x){register int c = gc();x = 0;int neg = 0;for(;((c<48 | c>57) && c != '-');c = gc());
          if(c=='-') {neg=1;c=gc();}for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}if(neg) x=-x;}
    Long bigmod(Long p,Long e,Long M){Long ret = 1;for(; e > 0; e >>= 1){if(e & 1) ret = (ret * p) % M;p = (p * p) % M;} return ret;}
    Long gcd(Long a,Long b){if(b==0)return a;return gcd(b,a%b);}
    Long modinverse(Long a,Long M){return bigmod(a,M-2,M);}
    void io(){freopen("/Users/MyMac/Desktop/in.txt","r",stdin);}
    
    /*************************** END OF TEMPLATE ****************************/
    
    const int N = 2e5+5;
    int wa[N],wb[N],wv[N],wc[N];
    int r[N],sa[N],rak[N], height[N];
    int cmp(int *r,int a,int b,int l)
    {
          return r[a] == r[b] && r[a+l] == r[b+l];
    }
    void da(int *r,int *sa,int n,int m)
    {
          int i,j,p,*x=wa,*y=wb,*t;
          for( i=0;i<m;i++) wc[i]=0;
          for( i=0;i<n;i++) wc[x[i]=r[i]] ++;
          for( i=1;i<m;i++) wc[i] += wc[i-1];
          for( i= n-1;i>=0;i--)sa[--wc[x[i]]] = i;
          for( j= 1,p=1;p<n;j*=2,m=p){
                for(p=0,i=n-j;i<n;i++)y[p++] = i;
                for(i=0;i<n;i++)if(sa[i] >= j) y[p++] = sa[i] - j;
                for(i=0;i<n;i++) wv[i] = x[y[i]];
                for(i=0;i<m;i++) wc[i] = 0;
                for(i=0;i<n;i++) wc[wv[i]] ++;
                for(i=1;i<m;i++) wc[i] += wc[i-1];
                for(i=n-1;i>=0;i--) sa[--wc[wv[i]]] = y[i];
                for(t=x,x=y,y=t,p=1,x[sa[0]] = 0,i=1;i<n;i++) x[sa[i]]= cmp(y,sa[i-1],sa[i],j) ? p-1:p++;
    
          }
    }
    
    void calheight(int *r,int *sa,int n)
    {
          int i,j,k=0;
          for(i=1;i<=n;i++) rak[sa[i]] = i;
          for(i=0;i<n;height[rak[i++]] = k ) {
                for(k?k--:0, j=sa[rak[i]-1] ; r[i+k] == r[j+k] ; k ++) ;
          }
    }
    
    int id[N];
    vector<int> Pi[N];
    bool can(int mid,int n,int type,int k)
    {
          bool vis[110];
          ms(vis,0);
          int flag = false, in = false;
          int cnt = 0;
          for(int i= 1;i <= n;i++ ) {
                if(height[i] >= mid){
                            if(vis[id[sa[i]]] ==0 ) {
                                  vis[id[sa[i]]] = 1;
                                  cnt ++;
                            }
                            if(cnt > k/2 ) {
                                  flag=1;
                                  if(!in) {
                                        in = true;
                                        Pi[mid].pb(sa[i]);
                                  }
                            }
                }else {
                      ms(vis,0);
                      vis[id[sa[i]]] = 1;
                      cnt=1;
                      in = false;
                }
          }
          return flag;
    }
    
    char str[N];
    int main()
    {
          //freopen("in.txt","r",stdin);
          int k;
          int cs = 0;
          while(scanf("%d",&k)==1){
                if(k==0) break;
                int p = 0;
                ms(id,0);
                for(int i =0; i< k;i ++) {
                      scanf("%s",str);
                      for(int j= 0; str[j] ; j ++ , p ++ ) {
                            r[p] = str[j] - 'a' + 1;
                            id[p] = i+1;
                      }
                      r[p++] =27+i;
                }
                p--;
                r[p] = 0;
                da(r,sa,p+1,130);
                calheight(r,sa,p);
                /*
                for(int i=0;i<=p;i++) printf("%d ",sa[i]);
                printf("\n");
                for(int i=0;i<=p;i++) printf("%d ",height[i]);
                      */
                int low= 0, high = p-1, ans = 0,mid;
                while(low <= high) {
                      mid = (low+ high) /2;
                      if(can(mid,p,0,k)) {
                            ans = mid;
                            low = mid+1;
                      }else high = mid-1;
    
    
                }
                if(cs) printf("\n");
                if(ans) {
                      for(int i = 0;i < Pi[ans].size(); i ++ ) {
                            int pivot = Pi[ans][i];
                            for(int j = 0;j < ans; j ++) printf("%c",r[j+pivot] -1 + 'a');
                            printf("\n");
                      }
                }else printf("?\n");
                cs = 1;
                for(int i= 0;i<=p;i++) Pi[i].clear();
          }
          return 0;
    }
    
    

    Suffix-array

    Suffix-array is an important data structure for string.
    Details of suffix array can be found in This link

    Binary Search becomes helpful in this kind of problem.

    Problem Link : POJ 3261

    
    /*
    
     *************************
     Id  : Matrix.code
     Task: POJ - 3261
     Date: 2016-01-16
    
     **************************
    
     */
    #include<vector>
    #include<list>
    #include<deque>
    #include<queue>
    #include<stack>
    #include<map>
    #include<set>
    #include<bitset>
    #include<algorithm>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cctype>
    #include<cmath>
    #include<ctime>
    using namespace std;
    
    /*------- Constants---- */
    
    #define Long                    long long
    #define ull                     unsigned long long
    #define mod                     1000000007
    #define MEMSET_INF              63
    #define MEM_VAL                 1061109567
    #define forn(i,n)               for( int i=0 ; i < n ; i++ )
    #define mp(i,j)                 make_pair(i,j)
    #define lop(i,a,b)              for( int i = (a) ; i < (b) ; i++)
    #define pb(a)                   push_back((a))
    #define SZ(a)                   (int) a.size()
    #define all(x)                  (x).begin(),(x).end()
    #define gc                      getchar_unlocked
    #define PI                      acos(-1.0)
    #define INF                     1<<29
    #define EPS                     1e-9
    #define Fr                      first
    #define Sc                      second
    #define Sz                      size()
    #define lc                      ((n)<<1)
    #define rc                      ((n)<<1|1)
    #define db(x)                   cout << #x << " -> " << x << endl;
    #define Di(n)                   int n;si(n)
    #define Dii(a,b)                int a,b;si(a);si(b)
    #define Diii(a,b,c)             int a,b,c;si(a);si(b);si(c)
    #define Si(n)                   si(n)
    #define Sii(a,b)                si(a);si(b)
    #define Siii(a,b,c)             si(a);si(b);si(c)
    #define min(a,b)                ((a)>(b) ? (b) : (a) )
    #define max(a,b)                ((a)>(b) ? (a):(b))
    /*---- short Cuts ------- */
    #define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
    typedef pair<int, int> ii;
    typedef vector<int > vi ;
    typedef vector<Long> vl;
    /*------ template functions ------ */
    #ifndef getchar_unlocked
    #define getchar_unlocked getchar
    #endif
    template<class T> inline void si(T &x){register int c = gc();x = 0;int neg = 0;for(;((c<48 | c>57) && c != '-');c = gc());
          if(c=='-') {neg=1;c=gc();}for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}if(neg) x=-x;}
    Long bigmod(Long p,Long e,Long M){Long ret = 1;for(; e > 0; e >>= 1){if(e & 1) ret = (ret * p) % M;p = (p * p) % M;} return ret;}
    Long gcd(Long a,Long b){if(b==0)return a;return gcd(b,a%b);}
    Long modinverse(Long a,Long M){return bigmod(a,M-2,M);}
    void io(){freopen("/Users/MyMac/Desktop/in.txt","r",stdin);}
    
    /*************************** END OF TEMPLATE ****************************/
    
    const int N = 2e4+4;
    int wa[N],wb[N],wv[N],wc[N];
    int r[N],sa[N],rak[N], height[N];
    
    // compare of two suffix starting at a & b and gap = l
    int cmp(int *r,int a,int b,int l)
    {
          return r[a] == r[b] && r[a+l] == r[b+l];
    }
    void da(int *r,int *sa,int n,int m)
    {
          int i,j,p,*x=wa,*y=wb,*t;
          for( i=0;i<m;i++) wc[i]=0;
          for( i=0;i<n;i++) wc[x[i]=r[i]] ++;
          for( i=1;i<m;i++) wc[i] += wc[i-1];
          for( i= n-1;i>=0;i--)sa[--wc[x[i]]] = i;
          for( j= 1,p=1;p<n;j*=2,m=p){
                for(p=0,i=n-j;i<n;i++)y[p++] = i;
                for(i=0;i<n;i++)if(sa[i] >= j) y[p++] = sa[i] - j;
                for(i=0;i<n;i++)wv[i] = x[y[i]];
                for(i=0;i<m;i++) wc[i] = 0;
                for(i=0;i<n;i++) wc[wv[i]] ++;
                for(i=1;i<m;i++) wc[i] += wc[i-1];
                for(i=n-1;i>=0;i--) sa[--wc[wv[i]]] = y[i];
                for(t=x,x=y,y=t,p=1,x[sa[0]] = 0,i=1;i<n;i++) x[sa[i]]= cmp(y,sa[i-1],sa[i],j) ? p-1:p++;
    
          }
    }
    
    void calheight(int *r,int *sa,int n)
    { // height[i] = longest common prefix of (Suffix (sa[i]) & Suffix(sa[i-1]) 
          int i,j,k=0;
          for(i=1;i<=n;i++) rak[sa[i]] = i;
          for(i=0;i<n; i++  ) {
                if(k) k--;
                j = sa[rak[i] - 1];
                while(r[i+k] == r[j+k]) k++;
                height[rak[i]] = k;
          }
    }
    
    bool can(int mid,int n,int k )
    {
          int cnt=1;
          for(int i=2;i<=n;i++){
                if(height[i] < mid) cnt=1;
                else cnt ++;
                if(cnt >= k) return 1;
          }
          return 0;
    }
    
    int a[N];
    int main()
    {
          //freopen("in.txt","r",stdin);
          Dii(n,k);
          int cnt = 0;
          forn(i,n){
                Si(a[i]);
                r[i] = a[i] + 1;
                cnt = max(cnt,r[i]);
          }
          r[n] = 0;
          da(r,sa,n+1,cnt+1);
          calheight(r,sa,n);
          int low= 1,high = n, ans=0,mid;
          while(low <= high) {
                mid = (low + high) / 2;
                if(can(mid,n,k)) {
                      ans = mid;
                      low=  mid+1;
                }else high = mid-1;
          }
          printf("%d\n", ans);
    
    
          return 0;
    }