Josephus problem

From : Rosetta

Josephus problem is a math puzzle with a grim description: n prisoners are standing on a circle, sequentially numbered from 0 to n − 1.

An executioner walks along the circle, starting from prisoner 0, removing every k-th prisoner and killing him.

As the process goes on, the circle becomes smaller and smaller, until only one prisoner remains, who is then freed.
For example, if there are n = 5 prisoners and k = 2, the order the prisoners are killed in (let’s call it the “killing sequence”) will be 1, 3, 0, and 4, and the survivor will be #2.

Task Given any n,k > 0, find out which prisoner will be the final survivor. In one such incident, there were 41 prisoners and every 3rd prisoner was being killed (k = 3). Among them was a clever chap name Josephus who worked out the problem, stood at the surviving position, and lived on to tell the tale. Which number was he?

How To solve ?

There are n people in a circle, and people counts from 1 to k, and the person who count k will be eliminated. And we keep this process until there is only 1 person left in the circle.

Let’s first number position of these n people: 0, 1, 2, …, n-1. You notice that we change number from [1,2…n] to [0,1,…n-1], this is because of module operation. Likewise, people will now count from 0 to k-1, and the person who count k-1 will be eliminated.

The first person to be eliminated is in position (k-1)%n. After the first person has been eliminated, the circle now has only n-1 people left. One key discovery is that the last person who is finally eliminated(we call him lucky guy) is the same one to be eliminated in n-1 people circle!

Now we begin eliminate the second person:

Since (k-1)%n is the position that the first person got eliminated, then k%n must be the 0-th position for this round.

So we can number accordingly in the following table:

Position in first round ———-Position in second round
k%n ——————————— 0
k%n+1 ——————————- 1
k%n+2 ——————————- 2

….

Let’s assume the lucky guy in the first round in position: f(n, k).
Then the same lucky guy in the second round in position: f(n-1, k)

So, based on the table, we know the lucky guy in second round who is in position f(n-1, k), must be in position k%n+f(n-1,k) in the first round.

Position in first round ———-Position in second round
k%n ———————————- 0
k%n+1 ——————————– 1
k%n+2 ——————————– 2

k%n+f(n-1,k) ——————- f(n-1,k)

So, we know f(n,k) = k%n + f(n-1,k), to avoid over the range, we make it f(n,k) = (k%n + f(n-1,k)) % n = (k + f(n-1,k)) %n

Base Case : f(1,k) = 0;

Courtesy : Billionaire

Special Case :
k = 2,
We explicitly solve the problem when every 2nd person will be killed, i.e. k=2. We express the solution recursively. Let f(n) denote the position of the survivor when there are initially n people (and k=2). The first time around the circle, all of the even-numbered people die. The second time around the circle, the new 2nd person dies, then the new 4th person, etc.; it’s as though there were no first time around the circle.
If the initial number of people was even, then the person in position x during the second time around the circle was originally in position 2x – 1 (for every choice of x). Let n=2j. The person at f(j) who will now survive was originally in position 2f(j) – 1. This gives us the recurrence
f(2j)=2f(j)-1 ;.
If the initial number of people was odd, then we think of person 1 as dying at the end of the first time around the circle. Again, during the second time around the circle, the new 2nd person dies, then the new 4th person, etc. In this case, the person in position x was originally in position 2x+1. This gives us the recurrence
f(2j+1)=2f(j)+1 ;.

Problem : Problem

#include <bits/stdc++.h>
using namespace std;

/*------- Constants---- */

#define LL                      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 all(x)                  (x).begin(),(x).end()
#define gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define inf                     1<<30
#define lc                      ((n)<<1)
#define rc                      ((n)<<1 |1)
#define db(x)                   cout << #x << " -> " << x << endl;
#define DI(n)                   int n;sc(n)
#define DII(a,b)                int a,b;sc(a);sc(b)
#define DIII(a,b,c)             int a,b,c;sc(a);sc(b);sc(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 ;
/*------ template functions ------ */
#ifndef getchar_unlocked
#define getchar_unlocked getchar
#endif
template<class T> inline void sc(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;}
template <class T> inline T bigmod(T p,T e,T M){LL ret = 1;for(; e > 0; e >>= 1){if(e & 1) ret = (ret * p) % M;p = (p * p) % M;} return (T)ret;}
template <class T> inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template <class T> inline T modinverse(T a,T M){return bigmod(a,M-2,M);}

/*************************** END OF TEMPLATE ****************************/
const int N = 2005;
char st[10];

int calc(int n)
{
      if(n==1) return 1;
      if(n%2==0) return 2*calc(n/2) - 1;
      else return 2 * calc(n/2) + 1;
}
int main()
{
      while(1){
            scanf("%s",st);
            int n = (st[0] -'0') * 10 + st[1]-'0';
            int p = st[3] -'0';
            for(int i = 0; i<p;i++ ) n*=10;
            if(n==0) break;
            
            cout<< calc(n) << endl;
            
      }
      
}

Here Problem List
1. Musical Chairs
2. WTK
3. King</a
4.
UVA-10774

CF 348C & Heavy-Light

Problem : Link
Discussion:
From The editorial of this Problem,
First step of the solution is to divide sets to heavy and light. Light ones are those that contains less than elements. All other sets are heavy.

Key observation is that every light set contains less than elements and number of heavy sets doesn’t exceed because we have upper bound for sum of the sizes of all sets.

In order to effectively answer queries, for every set (both light and heavy) we calculate size of the intersection of this set and each heavy set. It can be done with time and memory . For every heavy set we create boolean array of size O(n). In i-th cell of this array we store how many elements i in given set. Then for each element and each heavy set we can check for O(1) time whether element is in the set.

Now let’s consider 4 possible cases:

Add to the light set. Traverse all numbers in the set and add the value from the query to each of them. Then traverse all heavy sets and add (size of intersection * the value from the query). Time is .

Add to the heavy set. Just update the counter for the heavy set. Time is O(1).

Answer to the query for the light set. Traverse all numbers in the set and add values to the answer. Then traverse all heavy sets and add to the answer (answer for this heavy set * size of intersection with the set in the query). Time is .

Answer to the query for the heavy set. Take already calculated answer, then traverse all heavy sets and add (answer for this heavy set * size of intersection with the set in the query). Time is .

We have O(n) queries so total time is .

How To implement ???
1. Separation of Heavy & Light Set
2. Calculation of intersection
3. Answer each Query

#define sqN 320
Ans1 : if Size of any set > sqN , It is heavy, otherwise light
Ans2 : Iterate through all the heavy set, For each index on this set, With help of Reversed vector, Count The intersection between Each set
Ans3 :
For each heavy Set, We keep an array which stores the updated sum
For each light set, Iterate through all the index and add ,Then traverse the heavy set


#include <bits/stdc++.h>
using namespace std;

/*------- Constants---- */

#define LL                      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 all(x)                  (x).begin(),(x).end()
#define gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define inf                     1<<30
#define lc                      ((n)<<1)
#define rc                      ((n)<<1 |1)
#define db(x)                   cout << #x << " -> " << x << endl;
#define DI(n)                   int n;sc(n)
#define DII(a,b)                int a,b;sc(a);sc(b)
#define DIII(a,b,c)             int a,b,c;sc(a);sc(b);sc(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 ;
/*------ template functions ------ */
#ifndef getchar_unlocked
#define getchar_unlocked getchar
#endif
template<class T> inline void sc(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;}
template <class T> inline T bigmod(T p,T e,T M){LL ret = 1;for(; e > 0; e >>= 1){if(e & 1) ret = (ret * p) % M;p = (p * p) % M;} return (T)ret;}
template <class T> inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template <class T> inline T modinverse(T a,T M){return bigmod(a,M-2,M);}

/*************************** END OF TEMPLATE ****************************/
const int N = 1e5+5;
LL A[N];
vector<int> Set[N];
LL Sum[N];

int sqN = 320;
vector<int> Heavy;
bool isHeavy[N];
int pos[N];
vector<int> R[N];
LL ins[320][N];
LL adh[N];

int main()
{
      DIII(n,m,q);
      for(int i=1;i<=n;i++) sc(A[i]);
      for(int i=1;i <=m ; i ++ ) {
            DI(s);
            forn(j,s){
                  DI(ind);
                  Set[i].pb(ind);
                  Sum[i] += A[ind];
                  R[ind].pb(i);
            }
            if(s >= sqN) {
                  pos[i] = Heavy.size();
                  Heavy.pb(i);
                  isHeavy[i] = 1;
                  
            }
      }
      for(int i =0 ;i < Heavy.size();i ++ ) {
            int k = Heavy[i];
            for(auto a : Set[k] ) {
                  for(auto b : R[a]) ins[i][b] ++;
            }
      }
      
      int k;
      char t[10];
      
      while(q--){
            scanf(" %s%d",t,&k);
            if(t[0]=='?'){
                  LL res = 0;
                  if(isHeavy[k] ) res  = Sum[k];
                  else {
                        for(auto a: Set[k]) res+= A[a];
                        forn(i,Heavy.size()) res += ins[i][k] * adh[Heavy[i]];
                  }
                  printf("%lld\n", res) ;
            }
            else {
                  DI(d);
                  if(isHeavy[k]) adh[k] += d;
                  else {
                        for(auto a: Set[k]) A[a] += d;
                  }
                  for(int i=0;i<Heavy.size() ;i ++) {
                        Sum[Heavy[i]] += ins[i][k] * d;
                  }
            }
      }
}

CF – 121E

Problem Link : Problem

This is very common question but hard to answer efficiently.This Problem, I have solved using Two methods.
1. Sqrt-Decomposition
2. Segment Tree with Lazy-Propagation

For First Approach:

* For each block ,cnt which represents which number occur how many time
* an delta Array for each block

For each query, I go-through the block & element,calculate the sum
For each update, Similar approach, cnt array change

Ok this code runs 3.93 sec where Time Limit = 4s.. Not a good solution I guess.

#include <bits/stdc++.h>
using namespace std;

/*------- Constants---- */

#define LL                      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 all(x)                  (x).begin(),(x).end()
#define gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define inf                     1<<30
#define lc                      ((n)<<1)
#define rc                      ((n)<<1 |1)
#define db(x)                   cout << #x << " -> " << x << endl;
#define DI(n)                   int n;sc(n)
#define DII(a,b)                int a,b;sc(a);sc(b)
#define DIII(a,b,c)             int a,b,c;sc(a);sc(b);sc(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 ;
/*------ template functions ------ */
#ifndef getchar_unlocked
#define getchar_unlocked getchar
#endif
template<class T> inline void sc(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;}
template <class T> inline T bigmod(T p,T e,T M){LL ret = 1;for(; e > 0; e >>= 1){if(e & 1) ret = (ret * p) % M;p = (p * p) % M;} return (T)ret;}
template <class T> inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template <class T> inline T modinverse(T a,T M){return bigmod(a,M-2,M);}

/*************************** END OF TEMPLATE ****************************/
const int N = 100005;
vector<int> Lucky;
bool L[10005];

void gen(int u)
{
      if(u>10000) return;
      if(u>0) Lucky.pb(u);
      gen(10*u+4);
      gen(10*u+7);
}

int A[N];


int block = 320;
int delta[500];
int cnt[500][10005];

void updateElement(int pos,int d)
{
      int id = pos/block;
      int prv= A[pos];
      cnt[id][prv] --;
      A[pos] += d;
      cnt[id][A[pos]] ++;
      
}

void updateBlock(int id,int d)
{
      delta[id] += d;
}
void update(int lo,int hi,int d)
{
      int i;
      for(i=lo; i%block&&i<=hi; i ++ ) {
            updateElement(i,d);
      }
      for(; i + block-1 <= hi; i += block) {
            updateBlock(i/block,d);
      }
      for(;i <= hi ; i ++ ) updateElement(i,d);
}

int queryElement(int pos)
{
      int id = pos/block;
      if(L[A[pos] + delta[id]] ) return 1;
      return 0;
}

int queryBlock(int id)
{
      int p = delta[id];
      int res = 0;
      for(int i = 0;i < Lucky.size() ; i++ ) {
            int c = Lucky[i] - p;
            if(c>0) res += cnt[id][c];
      }
      return res;
}

int query(int lo,int hi)
{
      int i,j;
      int res = 0;
      for(i=lo;i%block&&i<=hi;i++){
            res += queryElement(i);
      }
      for( ; i + block -1 <= hi ; i+= block){
            res += queryBlock(i/block);
      }
      for(;i<=hi;i++) res += queryElement(i);
      return res;
      
}
int main()
{
      gen(0);
      sort(all(Lucky));
      forn(i,Lucky.size()) L[Lucky[i]] = 1;
      
      DII(n,q);
      forn(i,n) sc(A[i]);
      
      forn(i,n){
            cnt[i/block][A[i]] ++;
      }
      
      int lo,hi;
      char t[10];
      while(q--){
            scanf("%s%d%d",t,&lo,&hi);
            lo--,hi--;
            if(t[0]=='c'){
                  int res = query(lo,hi);
                  printf("%d\n",res);
            }
            else {
                  DI(d);
                  update(lo,hi,d);
                  
            }
      }
      
}

With Simple optimization This program can run under 1s.
The optimisation is :
We store The value for each block until The whole block is updated.
Then for quering block, Check , Is the value is already calculated or not.
If calculated then return ans, else calculate manually and store the value


#include <bits/stdc++.h>
using namespace std;

/*------- Constants---- */

#define LL                      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 all(x)                  (x).begin(),(x).end()
#define gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define inf                     1<<30
#define lc                      ((n)<<1)
#define rc                      ((n)<<1 |1)
#define db(x)                   cout << #x << " -> " << x << endl;
#define DI(n)                   int n;sc(n)
#define DII(a,b)                int a,b;sc(a);sc(b)
#define DIII(a,b,c)             int a,b,c;sc(a);sc(b);sc(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 ;
/*------ template functions ------ */
#ifndef getchar_unlocked
#define getchar_unlocked getchar
#endif
template<class T> inline void sc(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;}
template <class T> inline T bigmod(T p,T e,T M){LL ret = 1;for(; e > 0; e >>= 1){if(e & 1) ret = (ret * p) % M;p = (p * p) % M;} return (T)ret;}
template <class T> inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template <class T> inline T modinverse(T a,T M){return bigmod(a,M-2,M);}

/*************************** END OF TEMPLATE ****************************/
const int N = 100005;
vector<int> Lucky;
bool L[10005];

void gen(int u)
{
      if(u>10000) return;
      if(u>0) Lucky.pb(u);
      gen(10*u+4);
      gen(10*u+7);
}

int A[N];

int ia[N];
int block = 320;
int delta[500];
int cnt[500][10005];

void updateElement(int pos,int d)
{
      int id = pos/block;
      if(ia[id]!=-1 && L[A[pos] + delta[id]]) ia[id] --;
      cnt[id][A[pos]] --;
      A[pos] += d;
      cnt[id][A[pos]] ++;
      
      if(ia[id]!=-1 && L[A[pos] + delta[id]]) ia[id] ++;
}

void updateBlock(int id,int d)
{
      delta[id] += d;
      ia[id] = -1;
}
void update(int lo,int hi,int d)
{
      int i;
      for(i=lo; i%block&&i<=hi; i ++ ) {
            updateElement(i,d);
      }
      for(; i + block-1 <= hi; i += block) {
            updateBlock(i/block,d);
      }
      for(;i <= hi ; i ++ ) updateElement(i,d);
}

int queryElement(int pos)
{
      int id = pos/block;
      if(L[A[pos] + delta[id]] ) return 1;
      return 0;
}

int queryBlock(int id)
{
      if(ia[id]>=0) return ia[id];
      int p = delta[id];
      int res = 0;
      for(int i = 0;i < Lucky.size() ; i++ ) {
            int c = Lucky[i] - p;
            if(c>0) res += cnt[id][c];
      }
      return ia[id] = res;
}

int query(int lo,int hi)
{
      int i,j;
      int res = 0;
      for(i=lo;i%block&&i<=hi;i++){
            res += queryElement(i);
      }
      for( ; i + block -1 <= hi ; i+= block){
            res += queryBlock(i/block);
      }
      for(;i<=hi;i++) res += queryElement(i);
      return res;
      
}
int main()
{
      ms(ia,-1);
      gen(0);
      sort(all(Lucky));
      forn(i,Lucky.size()) L[Lucky[i]] = 1;
      
      DII(n,q);
      forn(i,n) sc(A[i]);
      
      forn(i,n){
            cnt[i/block][A[i]] ++;
      }
      
      int lo,hi;
      char t[10];
      while(q--){
            scanf("%s%d%d",t,&lo,&hi);
            lo--,hi--;
            if(t[0]=='c'){
                  int res = query(lo,hi);
                  printf("%d\n",res);
            }
            else {
                  DI(d);
                  update(lo,hi,d);
                  
            }
      }
      
}

Segment Tree Solution with lazy – propagration :
For each node in the segment Tree
1. If it is a leaf node, Store The value,distance to the nearest lucky number , lazy value, sum
2. If not , Then store sum , near,lazy

struct Node
{
      int sum,near,lazy,v;
      Node(){sum=0,near=inf,lazy=0,v=-1;}
};

Merging The tree :
The whole node ,stores The nearest distance to the lucky number among all the elements of the segments
So merging will calculate, minimum of left child and right child
The sum = sum_of_Left + sum_of_Right;

void Merge(int n)
{
      T[n].near = min(T[lc].near - T[lc].lazy , T[rc].near - T[rc].lazy);
      T[n].sum = T[lc].sum + T[rc].sum;
}

Building The Tree :

void build(int n,int b,int e)
{
      if(b==e){
            T[n].near= dis[A[b]];
            T[n].v = A[b];
            T[n].sum = L[A[b]];
            T[n].lazy = 0;
            return;
      }
      
      int mid = (b+e)/2;
      build(lc,b,mid);
      build(rc,mid+1,e);
      Merge(n);
}

For lazy Propagation We need to push
The function for this

void push(int n)
{

      T[lc].lazy += T[n].lazy;
      T[rc].lazy += T[n].lazy;
      
      if(T[n].lazy) { T[n].near -= T[n].lazy;T[n].lazy = 0;}
      if(T[n].sum == 0 ) T[lc].sum = T[rc].sum = 0;
      
}

Query is same as the standard query Function

int query(int n,int b,int e,int i,int j)
{
      
      if(b>=i&&e<=j) return T[n].sum;
      if(b!=e) push(n);
      int mid = (b+e)/2;
      int ret =0;
      if(i<=mid)ret += query(lc,b,mid,i,j);
      if(j>mid)ret += query(rc,mid+1,e,i,j);
      return ret;
      
}

Update : Update is Tricky,
1. If There is any chance that, We have attained or crossed a lucky Number , We go to that index( all the indices,and update them)
2. If for a segment , The distance to the nearest lucky Number > val(To add ) + lazy , Then There can be no lucky Number on this segment, T[n].sum = 0, return;

void update(int n,int b,int e,int i,int j,int val)
{
      if(b!=e) push(n);
      if(b>= i && e<= j ) {
            if(b==e){
                  T[n].v += T[n].lazy + val;
                  T[n].lazy = 0;
                  T[n].sum =L[T[n].v];
                  T[n].near = dis[T[n].v];
                  return ;
            }
            if(T[n].near > T[n].lazy + val ){
                  T[n].lazy += val;
                  T[n].sum = 0;
                  return ;
            }
      }
      
      int mid = (b+e)/2;
      if(i<=mid) update(lc,b,mid,i,j,val);
      if(j>mid)update(rc,mid+1,e,i,j,val);
      Merge(n);
      
}

FinalCode:


#include <bits/stdc++.h>
using namespace std;

/*------- Constants---- */

#define LL                      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 all(x)                  (x).begin(),(x).end()
#define gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define inf                     1<<30
#define lc                      ((n)<<1)
#define rc                      ((n)<<1 |1)
#define db(x)                   cout << #x << " -> " << x << endl;
#define DI(n)                   int n;sc(n)
#define DII(a,b)                int a,b;sc(a);sc(b)
#define DIII(a,b,c)             int a,b,c;sc(a);sc(b);sc(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 ;
/*------ template functions ------ */
#ifndef getchar_unlocked
#define getchar_unlocked getchar
#endif
template<class T> inline void sc(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;}
template <class T> inline T bigmod(T p,T e,T M){LL ret = 1;for(; e > 0; e >>= 1){if(e & 1) ret = (ret * p) % M;p = (p * p) % M;} return (T)ret;}
template <class T> inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template <class T> inline T modinverse(T a,T M){return bigmod(a,M-2,M);}

/*************************** END OF TEMPLATE ****************************/
const int N = 1e5+5;
vector<int> Lucky;
bool L[N];
int A[N];
int dis[N];

void gen(int u)
{
      if(u>10000) return;
      if(u>0) Lucky.pb(u);
      gen(10*u+4);
      gen(10*u+7);
}

struct Node
{
      int sum,near,lazy,v;
      Node(){sum=0,near=inf,lazy=0,v=-1;}
};

Node T[4*N];


void Merge(int n)
{
      T[n].near = min(T[lc].near - T[lc].lazy , T[rc].near - T[rc].lazy);
      T[n].sum = T[lc].sum + T[rc].sum;
}

void push(int n)
{

      T[lc].lazy += T[n].lazy;
      T[rc].lazy += T[n].lazy;
      
      if(T[n].lazy) { T[n].near -= T[n].lazy;T[n].lazy = 0;}
      if(T[n].sum == 0 ) T[lc].sum = T[rc].sum = 0;
      
}

void build(int n,int b,int e)
{
      if(b==e){
            T[n].near= dis[A[b]];
            T[n].v = A[b];
            T[n].sum = L[A[b]];
            T[n].lazy = 0;
            return;
      }
      
      int mid = (b+e)/2;
      build(lc,b,mid);
      build(rc,mid+1,e);
      Merge(n);

}


int query(int n,int b,int e,int i,int j)
{
      
      if(b>=i&&e<=j) return T[n].sum;
      if(b!=e) push(n);
      int mid = (b+e)/2;
      int ret =0;
      if(i<=mid)ret += query(lc,b,mid,i,j);
      if(j>mid)ret += query(rc,mid+1,e,i,j);
      return ret;
      
}

void update(int n,int b,int e,int i,int j,int val)
{
      if(b!=e) push(n);
      if(b>= i && e<= j ) {
            if(b==e){
                  T[n].v += T[n].lazy + val;
                  T[n].lazy = 0;
                  T[n].sum =L[T[n].v];
                  T[n].near = dis[T[n].v];
                  db("akshd");
                  return ;
            }
            if(T[n].near > T[n].lazy + val ){
                  T[n].lazy += val;
                  T[n].sum = 0;
                  return ;
            }
      }
      
      int mid = (b+e)/2;
      if(i<=mid) update(lc,b,mid,i,j,val);
      if(j>mid)update(rc,mid+1,e,i,j,val);
      Merge(n);
      
}
int main()
{
      gen(0);
      dis[N-1] = inf;
      for(auto a : Lucky) L[a] = 1;
      for(int i = N-2; i >= 0; i-- ) {
            if(L[i+1]) dis[i]= 1;
            else dis[i] = 1 + dis[i+1];
      }
      DII(n,q);
      forn(i,n){
            sc(A[i]);
      }
      
      build(1,0,n-1);
      char op[10];
      int lo,hi;
      
      forn(i,q){
            scanf("%s%d%d",op,&lo,&hi);
            lo--,hi--;
            if(op[0]=='c'){
                  printf("%d\n", query(1,0,n-1,lo,hi));
            }
            else {
                  DI(d);
                  update(1,0,n-1,lo,hi,d);
            }
      }
      
}

Bit Range Minimum Query & Segment Tree

Intented Problem : Link

Okay.I first tried to solve this using segment tree.

My Approach :
For each index i, I calculated the index of next element of the array which is equal to ia[i]
I calculated The array iA , using This information and a map. Build a segment tree with array iA,

Now to process each query, I found the minimum in range [i,j] using segment tree.
After quering i, I update the value of nxt[i] with inf


#include <bits/stdc++.h>
using namespace std;

/*------- Constants---- */

#define LL                      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 gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define inf                     1<<30
#define lc                      ((n)<<1)
#define rc                      ((n)<<1 |1)
#define db(x)                   cout << #x << " -> " << x << endl;
#define DI(n)                   int n;sc(n)
#define DII(a,b)                int a,b;sc(a);sc(b)
#define DIII(a,b,c)             int a,b,c;sc(a);sc(b);sc(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 ;
/*------ template functions ------ */
#ifndef getchar_unlocked
#define getchar_unlocked getchar
#endif
template<class T> inline void sc(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;}
template <class T> inline T bigmod(T p,T e,T M){LL ret = 1;for(; e > 0; e >>= 1){if(e & 1) ret = (ret * p) % M;p = (p * p) % M;} return (T)ret;}
template <class T> inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template <class T> inline T modinverse(T a,T M){return bigmod(a,M-2,M);}

/*************************** END OF TEMPLATE ****************************/
const int N = 5e5+5;
int ia[N];
vector<ii> v[N];
map<int,int> kl;
int T[4*N];
int iA[N];

void build(int n,int b,int e)
{
      if(b==e){
            T[n] = iA[b];return;
      }
      int mid = (b+e)/2;
      build(lc,b,mid);
      build(rc,mid+1,e);
      T[n] = min(T[lc],T[rc]);
}

int query(int n,int b,int e,int i,int j)
{
      if(b>j||e<i)return inf;
      if(b>=i&&e<=j) return T[n];
      int mid = (b+e)/2;
      return min(query(lc,b,mid,i,j) , query(rc,mid+1,e,i,j));
}

void update(int n,int b,int e,int pos,int val)
{
      if(b==e){T[n]=val;return;}
      int mid = (b+e)/2;
      if(pos<=mid) update(lc,b,mid,pos,val);
      else update(rc,mid+1,e,pos,val);
      T[n] = min(T[lc],T[rc]);
      
}
int ans[N];
int nxt[N];

int main()
{
      DII(n,m);
      lop(i,1,n+1) sc(ia[i]);
      forn(i,m){
            DII(l,r);
            v[l].pb(mp(r,i));
      }
      
      for(int i=1;i<=n;i++) {
            int dist= inf;
            if(kl.count(ia[i]) ) {
                  int prv = kl[ia[i]];
                  nxt[prv] = i;
                  dist = min(dist, i - prv) ;
            }
            kl[ia[i]] = i;
            iA[i] = dist; // Update each index with The distance of the same number in the array

      }
      
      build(1,1,n);
      for(int i = 1; i<= n;i ++ ) {
            for(auto a: v[i]){
                  int r = a.first;
                  int iv = a.second;
                  int c= query(1,1,n,1,r); // Query The minimum distance in the array
                  ans[iv] = c;
            }
            int nt = nxt[i];
            update(1,1,n,nt,inf );     // Now Process with i is end, Update nxt[i] with inf
      }
      
      for(int i =0 ;i < m ; i ++ ) {
            if(ans[i] == inf ) printf("-1\n");
            else printf("%d\n" , ans[i]);
      }
}

And This solution got TLE..

I implemented The same logic but in reverse order using BIT , and get AC..



#include <bits/stdc++.h>
using namespace std;

/*------- Constants---- */

#define LL                      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 gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define inf                     1<<30
#define lc                      ((n)<<1)
#define rc                      ((n)<<1 |1)
#define db(x)                   cout << #x << " -> " << x << endl;
#define DI(n)                   int n;sc(n)
#define DII(a,b)                int a,b;sc(a);sc(b)
#define DIII(a,b,c)             int a,b,c;sc(a);sc(b);sc(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 ;
/*------ template functions ------ */
#ifndef getchar_unlocked
#define getchar_unlocked getchar
#endif
template<class T> inline void sc(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;}
template <class T> inline T bigmod(T p,T e,T M){LL ret = 1;for(; e > 0; e >>= 1){if(e & 1) ret = (ret * p) % M;p = (p * p) % M;} return (T)ret;}
template <class T> inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template <class T> inline T modinverse(T a,T M){return bigmod(a,M-2,M);}

/*************************** END OF TEMPLATE ****************************/
const int N = 5e5+5;
int ia[N];
vector<ii> v[N];
map<int,int> M;
const int B= 1<<19;
int Bit[B+5];

int ans[N];
int nxt[N];


void update(int x,int val)
{
// The update is reverse in normal direction
      for(int i = x; i> 0; i -= i&-i){
            Bit[i] = min(Bit[i] , val);
      }
}

int query(int x)
{
// Reversed
      int ret = inf;
      for(int i = x; i<= B; i += i&-i) ret = min(ret,Bit[i]);
      return ret;
}
int main()
{
      DII(n,m);
      lop(i,1,n+1) sc(ia[i]);
      forn(i,B+1) Bit[i] = inf;
      forn(i,m){
            DII(l,r);
            v[r].pb(mp(l,i));
      }
      for(int i=1;i<=n;i++){
            if(M.find(ia[i]) != M.end()) update(M[ia[i]] , i - M[ia[i]]);
            M[ia[i]] = i;
            for(int j=0;j<v[i].size() ; j++) {
                  ans[v[i][j].second] = query(v[i][j].first);
            }
      }
      for(int i = 0; i<m ;i ++ ) {
            printf("%d\n" , ans[i] == inf ? -1 : ans[i]);
      }
      
}

SQRT – OPTIMISATION & Centroid Decomposition of a Tree

Problem : Link

Discussion :

Sqrt-Optimisation :
Split all queries into sqrt(m) blocks. Each block we will process separately. Before processing each block, we should calculate minimum distances from every node to the closest red node using bfs. To answer the query we should update this value by shortest distances to red nodes in current block.

The solution becomes simple. Every sqrt(m) queries we make simple bfs and for every node v WE calculate value d[v] — the shortest distance to some red node from node v. Then to answer the query of type 2 you should calculate min(d[v], dist(v, u)), where u — every red node, which becomes red in current block of length sqrt(m).

Distance between two nodes dist(u, v) can be got using preprocessing for lca.

Implementation :


#include <bits/stdc++.h>
using namespace std;

/*------- Constants---- */

#define LL                      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 gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define inf                     1<<30
#define lc                      ((n)<<1)
#define rc                      ((n)<<1 |1)
#define db(x)                   cout << #x << " -> " << x << endl;
#define DI(n)                   int n;sc(n)
#define DII(a,b)                int a,b;sc(a);sc(b)
#define DIII(a,b,c)             int a,b,c;sc(a);sc(b);sc(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 ;
/*------ template functions ------ */
#ifndef getchar_unlocked
#define getchar_unlocked getchar
#endif
template<class T> inline void sc(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;}
template <class T> inline T bigmod(T p,T e,T M){LL ret = 1;for(; e > 0; e >>= 1){if(e & 1) ret = (ret * p) % M;p = (p * p) % M;} return (T)ret;}
template <class T> inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template <class T> inline T modinverse(T a,T M){return bigmod(a,M-2,M);}

/*************************** END OF TEMPLATE ****************************/
const int N = 1e5+5;
const int LM = 20;
int INF = 1<<29;
vi G[N];
int P[N][LM];
int dep[N];
int d[N];


void dfs(int u,int p,int d)
{
      P[u][0] = p;
      for(int i= 1; i< LM; i ++ ) {
            if(P[u][i-1] !=-1 ) P[u][i] = P[P[u][i-1]][i-1];
            else P[u][i]= -1;
      }
      dep[u] = d;
      for(auto a: G[u]) if(a!=p){
            dfs(a,u,d+1);
      }
      
      
}



int op[N] , v[N];
vector<int> vs;

void bfs()
{
      queue<int> q;
      for(int i =0 ; i < vs.size() ; i ++ ) q.push(vs[i]) , d[vs[i]] = 0;
      while(!q.empty()) {
            int u = q.front();q.pop();
            for(auto a: G[u]) {
                  if(d[a] > d[u] + 1) {
                        d[a] = d[u]+1;
                        q.push(a);
                  }
            }
      }
}

int lca(int u,int v)
{
      if(dep[u] > dep[v]) swap(u,v);
      
      for(int i= LM-1;i>=0;i--){
            int nw = dep[v] - (1<<i);
            if(nw >= dep[u]) {
                  v =P[v][i];
            }
      }
      if(u==v)return u;
      for(int i = LM-1; i>= 0; i -- ) {
            if(P[u][i] != P[v][i]) {
                  u = P[u][i];
                  v = P[v][i];
            }
      }
      return P[v][0];
}

int main()
{
      DII(n,m);
      forn(i,n-1){
            DII(a,b);
            G[a].pb(b);
            G[b].pb(a);
      }
      
      
      
      forn(i,m) sc(op[i]),sc(v[i]);
      
      
      dfs(1,-1,0);
      forn(i,n+1)d[i] = INF;
      vs.pb(1);bfs();
      
      int B = 500;
      for(int i = 0; i < m; i += B ) {
            vs.clear();
            for(int j = 0; i + j < m && j < B ; j ++ ) {
                  if(op[i+j] == 1) {
                        vs.pb(v[i+j]);
                  }
                  else {
                        int iM = d[v[i+j]];
                        for(auto a : vs) {
                              int pp = lca(a,v[i+j]);
                              iM = min(iM , dep[a] - dep[pp] + dep[v[i+j]] - dep[pp]);
                        }
                        printf("%d\n", iM );
                  }
            }
            bfs();
      }
}

Centroid Decomposition of a Tree :
Discussion Link :




#include <bits/stdc++.h>
using namespace std;

/*------- Constants---- */

#define LL                      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 gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define inf                     1<<29
#define lc                      ((n)<<1)
#define rc                      ((n)<<1 |1)
#define db(x)                   cout << #x << " -> " << x << endl;
#define DI(n)                   int n;sc(n)
#define DII(a,b)                int a,b;sc(a);sc(b)
#define DIII(a,b,c)             int a,b,c;sc(a);sc(b);sc(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 ;
/*------ template functions ------ */
#ifndef getchar_unlocked
#define getchar_unlocked getchar
#endif
template<class T> inline void sc(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;}
template <class T> inline T bigmod(T p,T e,T M){LL ret = 1;for(; e > 0; e >>= 1){if(e & 1) ret = (ret * p) % M;p = (p * p) % M;} return (T)ret;}
template <class T> inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template <class T> inline T modinverse(T a,T M){return bigmod(a,M-2,M);}

/*************************** END OF TEMPLATE ****************************/
const int N = 1e5+5;
int SZ = 0;
const int LM = 17;
int P[N][LM];
vi G[N];
int sub[N];
int dep[N];
bool deleted[N];
int Par[N];


/***************** LCA *****************/
void dfs(int u,int p,int d=0)
{
      P[u][0] = p;
      dep[u] = d;
      for(int i=1;i<LM ; i++){
            if(P[u][i-1] !=-1 ) P[u][i] = P[P[u][i-1]][i-1];
      }
      for(auto a: G[u]) if(p!=a){
            dfs(a,u,d+1);
      }
}

int lca(int u,int v)
{
      if(dep[u] > dep[v]) swap(u,v);
      for(int i = LM-1; i>=0 ; i-- ) {
            int nw = dep[v]- (1<<i);
            if(nw >= dep[u]) v = P[v][i];
      }
      if(u==v)return v;
      for(int i= LM-1; i>=0 ; i-- ) {
            if(P[u][i] != P[v][i]) u = P[u][i], v=P[v][i];
      }
      return P[u][0];
}

int dist(int u,int v)
{
      int l = lca(u,v);
      return dep[u] + dep[v] - 2* dep[l];
}

/**************** DECOMPOSITION *************/
void dfs1(int u,int p)
{
      sub[u] =1;
      SZ ++;
      for(auto a: G[u]){
            if(a==p|| deleted[a] )continue;
            dfs1(a,u);
            sub[u] += sub[a];
      }
}

int find_root(int u,int p)
{
      
      for(auto a: G[u]) {
            if(a==p|| deleted[a]) continue;
            if(sub[a] > SZ/2) {
                  return find_root(a,u);
            }
      }
      return u;
}
void decompose(int u,int p)
{
      SZ = 0;
      dfs1(u,-1);
      int root = find_root(u,-1);
      Par[root] = p;
      deleted[root]  =1;
      
      for(auto a : G[root]) {
            if(deleted[a] || a == p )continue;
            decompose(a,root);
      }
}


/**********************************************/

int ans[N];
void update(int u)
{
      int v = u;
      while(v>0){
            ans [v] = min(ans[v] , dist(v,u));
            v = Par[v];
      }
      
}

int query(int u)
{
      int ret  = inf;
      int v = u;
      while(v>0){
            ret = min(ret , ans[v] + dist(v,u));
            v = Par[v];
      }
      return ret;
      
}


int main()
{
      ms(P,-1);
      DII(n,m);
      forn(i,n-1){
            DII(a,b);
            G[a].pb(b);
            G[b].pb(a);
      }
      dfs(1,-1);
      decompose(1,-1);
      
      forn(i,n+1) ans[i] = inf;
      update(1);
      forn(i,m){
            DII(t,k);
            if(t==1){
                  update(k);
            }
            else {
                  printf("%d\n", query(k));
            }
      }
      return 0;
}


Probability – Uva 10900 – So you want to be a 2n-aire?

Problem Link : Problem

Problem Statement:

You are a player on a quiz show. In the beginning, you have $1. For each correct answer this price doubles, but once you give a wrong answer, you lose everything. The game is over either after you decide to stop, or after you answer n questions.
Each time you are given a question, you think for a while, and come up with a possible answer. You can also estimate the probability p that your answer is correct. Based on this p you can decide whether you will stop playing (and take the current price), or try to answer the question.

Discussion:
Here is The tutorial : Misof

In a stage of game , I can quit and take whatever I had on this moment, Or attempt the question with probability p.
p is a random variable which value is given in range [r,1] .


For some values of p, it is profitable to attempt the question
For some values of p, it is profitable to just quit the game in this stage

Now lets define f(n,a) is the game state where I have answered n-1 question and Thinking about my best choice ?
If I quit the game I get = a amount of money
If I attempt the question with probability p , can get p * f(n+1,2*a) amount of money.
Let f(n+1,2*a) have returned us a value of K

Can you tell for which value of p in range [r,1] we should quit ???

This is simply for the range [r,K/a] ,Think about it ??

\frac { 1 }{ 1-t } \int _{ t }^{ 1 }{ \max { (a,p*f(n+1,2*a)) }  } dp

Let up is the spiliting point.

We can write

\frac { 1 }{ 1-t } (a\quad *\quad \int _{ r }^{ up }{ dp } \quad +\quad f(n+1,a)\quad *\quad \int _{ up }^{ 1 }{ p\quad dp\quad ) }

Now code


#include <bits/stdc++.h>
using namespace std;

/*------- Constants---- */

#define LL                      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 gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define inf                     1<<30
#define lc                      ((n)<<1)
#define rc                      ((n)<<1 |1)
#define db(x)                   cout << #x << " -> " << x << endl;
#define DI(n)                   int n;sc(n)
#define DII(a,b)                int a,b;sc(a);sc(b)
#define DIII(a,b,c)             int a,b,c;sc(a);sc(b);sc(c)
#define show(Ara,N)             for(int i = 0; i < N;i ++ ) printf("%d -> %d\n" , i , Ara[i])

/*---- short Cuts ------- */
#define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
typedef pair<int, int> ii;
typedef vector<int > vi ;
/*------ template functions ------ */
#ifndef getchar_unlocked
#define getchar_unlocked getchar
#endif
template<class T> inline void sc(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;
}
template <class T> inline T bigmod(T p,T e,T M){
	LL ret = 1;
	for(; e > 0; e >>= 1){
		if(e & 1) ret = (ret * p) % M;
		p = (p * p) % M;
	} return (T)ret;
}
template <class T> inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template <class T> inline T modinverse(T a,T M){return bigmod(a,M-2,M);}

/*************************** END OF TEMPLATE ****************************/
const int N = 100;
int n;
double r;

double calc(int q, double money)
{
      if(q==n)return money;
      
      double ret = 0;
      double nxt = calc(q+1,2*money);
      double up = money /nxt;
      if(up > r ) {
            ret += money * (up - r ) + .5 * (1- up * up )* nxt;
      }
      else ret += .5 * (1-r*r) * nxt;
      ret /= (1-r);
      return ret;
}

int main()
{
      
      while(1){
            sc(n);
            if(!n) break;
            scanf("%lf",&r);
            if(fabs(r-1) < 1e-7 ) {
                  printf("%.3lf\n", pow(2,n));
                  continue;
            }
            printf("%.3lf\n", calc(0,1));
            
      }
      return 0;
}


Probability ????

Probability Sometimes need dp , Sometimes we need to try all possible cases
Here is a problem
In this case , We need to enumerate all possible case
Problem Link : Link

Here N= 20, so total Number of subset = 2^20 ~ 10^6 which is managable. See the code



#include <bits/stdc++.h>
using namespace std;

/*------- Constants---- */

#define LL                      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 gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define inf                     1<<30
#define lc                      ((n)<<1)
#define rc                      ((n)<<1 |1)
#define db(x)                   cout << #x << " -> " << x << endl;
#define DI(n)                   int n;sc(n)
#define DII(a,b)                int a,b;sc(a);sc(b)
#define DIII(a,b,c)             int a,b,c;sc(a);sc(b);sc(c)
#define show(Ara,N)             for(int i = 0; i < N;i ++ ) printf("%d -> %d\n" , i , Ara[i])
#define min(a,b)                (a<b?a:b)
#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 ;
/*------ template functions ------ */
#ifndef getchar_unlocked
#define getchar_unlocked getchar
#endif
template<class T> inline void sc(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;
}
template <class T> inline T bigmod(T p,T e,T M){
	LL ret = 1;
	for(; e > 0; e >>= 1){
		if(e & 1) ret = (ret * p) % M;
		p = (p * p) % M;
	} return (T)ret;
}
template <class T> inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template <class T> inline T modinverse(T a,T M){return bigmod(a,M-2,M);}

/*************************** END OF TEMPLATE ****************************/

const int N = 23;
double ar[N];
double ind[N];

int main()
{
      
      int n,r,cs = 0;
      while(1){
            sc(n);
            sc(r);
            if(n+r==0)return 0;
            forn(i,n) scanf("%lf",&ar[i]);
            double tot  = 0;
            for(int i = 0; i < (1<<n) ; i ++ ) {
                  // Generating all the subset
                  int c= __builtin_popcount(i);
                  if(c==r){
                        double t = 1;
                        forn(j,n){
                              if(i&(1<<j)) t *= ar[j];      // If the j th person took a item
                              else t *= (1-ar[j]);          // If not took a item
                        }
                        tot += t;
                        forn(j,n){
                              if(i&(1<<j)) ind[j] += t;// Add the probability which satisfies
                        }
                        
                  }
            }
            
            printf("Case %d:\n",++cs);
            forn(i,n){
                  printf("%.6lf\n" , ind[i]/ tot);
            }
            ms(ind,0);
      }
      
      
}


Okay , This problem can be solved using DP.

//
//  main.cpp
//  11181 - Probability|Given
//
//  Created by Repon Macbook on 9/15/15.
//  Copyright (c) 2015 Repon Macbook. All rights reserved.
//


#include <bits/stdc++.h>
using namespace std;

/*------- Constants---- */

#define LL                      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 gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define inf                     1<<30
#define lc                      ((n)<<1)
#define rc                      ((n)<<1 |1)
#define db(x)                   cout << #x << " -> " << x << endl;
#define DI(n)                   int n;sc(n)
#define DII(a,b)                int a,b;sc(a);sc(b)
#define DIII(a,b,c)             int a,b,c;sc(a);sc(b);sc(c)
#define show(Ara,N)             for(int i = 0; i < N;i ++ ) printf("%d -> %d\n" , i , Ara[i])
#define min(a,b)                (a<b?a:b)
#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 ;
/*------ template functions ------ */
#ifndef getchar_unlocked
#define getchar_unlocked getchar
#endif
template<class T> inline void sc(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;
}
template <class T> inline T bigmod(T p,T e,T M){
	LL ret = 1;
	for(; e > 0; e >>= 1){
		if(e & 1) ret = (ret * p) % M;
		p = (p * p) % M;
	} return (T)ret;
}
template <class T> inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template <class T> inline T modinverse(T a,T M){return bigmod(a,M-2,M);}

/*************************** END OF TEMPLATE ****************************/

const int N = 23;
double ar[N];
int n,r;
double dp[N][N];
bool vis[N][N];
double calc(int r,int pos)
{
      if(r<0)return 0;
      if(pos==n){
            if(r==0) return 1;
            else return 0;
      }
      if(vis[r][pos] ) return dp[r][pos];
      
      double ret= 0;
      ret+= calc(r-1,pos+1) * ar[pos] + (1- ar[pos]) * calc(r,pos+1);
      vis[r][pos] = 1;
      return dp[r][pos] = ret;
}


double calc2(int r,int pos,int left)
{
      if(r<0) return 0;
      if(pos == n ) {
            if(r==0)return 1;
            else return 0;
      }
      if(vis[r][pos] ) return dp[r][pos];
      double ret = 0;
      if(pos==left) ret = calc2(r,pos+1,left);
      else ret += ar[pos] * calc2(r-1,pos+1,left) + (1-ar[pos])  * calc2(r,pos+1,left);
      vis[r][pos] = 1;
      return dp[r][pos] = ret;
}

int main()
{
      
      int cs = 0;
      while(1){
            sc(n);
            sc(r);
            if(n+r==0) break;
            forn(i,n) scanf("%lf",&ar[i]);
            ms(vis,0);
            double tot = calc(r,0);
            
            printf("Case %d:\n",++cs) ;
            forn(i,n)
            {
                  ms(vis,0);
                  double d = ar[i] * calc2(r-1,0,i);
                  printf("%.6lf\n", d/tot);
            }
      }
      
      return 0;
}


Using Recursion this can be solved

Practice Problem :

1. uva -10417

HackerRank – Number List 1D array Manupulation

Intended Problem : Problem
My Method :
I have calculated Which Number will present how many times in the new array. Then calculate the sum..


#include <bits/stdc++.h>
using namespace std;

/*------- Constants---- */

#define LL                      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 gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define inf                     1<<30
#define lc                      ((n)<<1)
#define rc                      ((n)<<1 |1)
#define db(x)                   cout << #x << " -> " << x << endl;
#define DI(n)                   int n;sc(n)
#define DII(a,b)                int a,b;sc(a);sc(b)
#define DIII(a,b,c)             int a,b,c;sc(a);sc(b);sc(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 ;
/*------ template functions ------ */
#ifndef getchar_unlocked
#define getchar_unlocked getchar
#endif
template<class T> inline void sc(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;
}
template <class T> inline T bigmod(T p,T e,T M){
	LL ret = 1;
	for(; e > 0; e >>= 1){
		if(e & 1) ret = (ret * p) % M;
		p = (p * p) % M;
	} return (T)ret;
}
template <class T> inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template <class T> inline T modinverse(T a,T M){return bigmod(a,M-2,M);}

/*************************** END OF TEMPLATE ****************************/
const int N = 2e5+5;
LL ar[N];
vector<LL> v;
LL prv[N], nxt[N];
LL occr[N];
LL tp[N];
LL csum[N];

int main()
{
      DI(tc);
      while(tc--){
            DI(n);
            DI(k);
            lop(i,1,n+1) {
                  sc(ar[i]);
                  v.pb(ar[i]);
            }
            sort(v.begin(), v.end());
            v.resize(unique(v.begin() , v.end()) - v.begin());
            for(int i = 1; i<= n; i ++ ) {
                  int j = i-1;
                  while(j>0 && ar[j] <= ar[i]) j = prv[j];
                  prv[i] = j;
            }
            for(int i = n; i > 0;i -- ) {
                  int j = i + 1;
                  while(j <= n && ar[j] < ar[i] ) j = nxt[j];
                  nxt[i] = j;
            }
            for(LL i = 1;i <= n; i ++ ) {
                  LL p = (i-prv[i] )  * (nxt[i] -i );
                  occr[i] = p;
                  int iL = lower_bound(v.begin(), v.end() , ar[i])- v.begin();
                  tp[iL] += p;
            }
            
            LL sum = 0;
            for(int i =0; i < v.size() ; i ++ ) {
                  if(v[i] > k ) sum += tp[i];
            }
            cout << sum << endl;
            v.clear();
            ms(tp,0);
            
      }
      
}

Geometry – Check if a Line segment intersect a circle or not ??

Intended Problem : Link
Solution : Tutorial

Discussion :

We will try to find whether the line segment `AB` intersects with the circle with center `C` and radius `r`.

It’s helpful to think of ‘A’ and ‘B’ as vectors, which you can scale, and add with other vectors. Thus, we can think of the line segment \xrightarrow { AB } as the set of points `P` such that:
P=A+(B-A)t

for some 0<= t <= 1 , and the circle with center `C` and radius `r` as the set of points `P` such that:
\sqrt { (P-C)\cdot (P-C) } =r

where `⋅` is the dot product (it is known that the length of a vector `V` is given by  \sqrt { V\cdot V } ).

Now we are trying to find a point `P` that belongs to both sets of points, so we substitute
 P=A+(B-A)t to the circle formula and manipulate to get:
Snip20150910_2

Snip20150910_3

There can be two, one, or no roots `t` (depending on the sign of the determinant `β2−αγ`). We simply check whether one of them is in the range `0≤t≤1`, and if so, we say that the segment intersects the circle!


In our intended Problem We need to handle Three edge of the triangle . If anyone of them intersect The circle Than Ans = "YES"
Or Ans = "NO"

Now code :



#include <bits/stdc++.h>
using namespace std;

/*------- Constants---- */

#define LL                      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 gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define inf                     1<<30
#define lc                      ((n)<<1)
#define rc                      ((n)<<1 |1)
#define db(x)                   cout << #x << " -> " << x << endl;
#define DI(n)                   int n;scanf("%d",&n)
#define DII(a,b)                int a,b;scanf("%d %d",&a,&b)
#define DIII(a,b,c)             int a,b,c;scanf("%d %d %d",&a,&b,&c)

/*---- short Cuts ------- */
#define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
typedef pair<int, int> ii;
typedef vector<int > vi ;
/*------ template functions ------ */
#ifndef getchar_unlocked
#define getchar_unlocked getchar
#endif
inline void sc(int &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;
}
template <class T> inline T bigmod(T p,T e,T M){
	LL ret = 1;
	for(; e > 0; e >>= 1){
		if(e & 1) ret = (ret * p) % M;
		p = (p * p) % M;
	} return (T)ret;
}
template <class T> inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template <class T> inline T modinverse(T a,T M){return bigmod(a,M-2,M);}
double INF = 1e100;
double EPS = 1e-12;


struct PT {
      LL  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 in(){scanf("%lld %lld",&x,&y);}
};

LL 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;}
LL 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);}

// rotate a point CCW or CW around the origin
PT RotCCW90(PT p){return PT(-p.y,p.x);}
PT RotCW90(PT p)   {return PT(p.y,-p.x);}
PT RotCCW(PT p,double ang) {return PT(p.x*cos(ang) - p.y*sin(ang) , p.x*sin(ang) + p.y * cos(ang));}

// project point c onto line through a and b
PT PPL (PT a,PT b,PT c){return a + (b-a)* dot(c-a,b-a) / dot(b-a,b-a);}

// project point c onto line segment through a and b
PT PPS(PT a, PT b, PT c) {
      double r = dot(b-a,b-a);
      if (fabs(r) < EPS) return a;
      r = dot(c-a, b-a)/r;
      if (r < 0) return a;
      if (r > 1) return b;
      return a + (b-a)*r;
}
// compute intersection of line through points a and b with
// circle centered at c with radius r > 0

vector<PT> CLIN(PT a, PT b, PT c, double r) {
      vector<PT> ret;
      b = b-a;
      a = a-c;
      double A = dot(b, b);
      double B = dot(a, b);
      double C = dot(a, a) - r*r;
      double D = B*B - A*C;
      if (D < -EPS) return ret;
      ret.push_back(c+a+b*(-B+sqrt(D+EPS))/A);
      if (D > EPS)
            ret.push_back(c+a+b*(-B-sqrt(D))/A);
      return ret;
}
/*************************** END OF TEMPLATE ****************************/
const int N = 2005;

PT O;
PT a,b,c;
LL r;

bool check(PT a, PT b)
{
      LL alp = dot(b-a,b-a);
      LL beta = dot(b-a,a-O);
      LL gama = dot(a-O,a-O) - r * r ;
      
      if(alp==0){
            if(beta) {
                  double t = -(double) gama/(2*beta);
                  if(t>=0 && t<= 1) return true;
            }else return false;
      }
      else {
            if(beta*beta-gama*alp>=0 ) {
                  double e1  = (-beta + sqrt(beta*beta-gama*alp) )/ alp;
                  double e2 = (-beta - sqrt(beta*beta-gama*alp) )/ alp;
                  if((e1>=0&&e1<=1) || (e2>=0 &&e2<=1) ) return 1;
                  return 0;
            }
            else return 0;
      }
      return 0;
}

int main()
{
      DI(tc);
      while(tc--){
            
            
            O.in();
            cin >> r;
            a.in();
            b.in();
            c.in();
            
            bool flag = 0;
            if(check(a,b) || check(b,c) || check(a,c) ) {
                  flag = 1;
            }
            
            printf("%s\n" , flag ? "YES" : "NO");
      }
      
}

Cayley’s Formula

Discussion : for every positive integer n, the number of trees on n labeled vertices is n^{n-2}.
For proof : http://www.math.uchicago.edu/~may/VIGRE/VIGRE2006/PAPERS/Casarotto.pdf
Problem Link : 10843 – Anne’s game
Solution :



#include <bits/stdc++.h>
using namespace std;

/*------- Constants---- */

#define LL                      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 gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define inf                     1<<30
#define lc                      ((n)<<1)
#define rc                      ((n)<<1 |1)
#define db(x)                   cout << #x << " -> " << x << endl;
#define DI(n)                   int n;sc(n)
#define DII(a,b)                int a,b;sc(a);sc(b)
#define DIII(a,b,c)             int a,b,c;sc(a);sc(b);sc(c)
#define show(Ara,N)             for(int i = 0; i < N;i ++ ) printf("%d -> %d\n" , i , Ara[i])

/*---- short Cuts ------- */
#define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
typedef pair<int, int> ii;
typedef vector<int > vi ;
/*------ template functions ------ */
#ifndef getchar_unlocked
#define getchar_unlocked getchar
#endif
template<class T> inline void sc(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;
}
template <class T> inline T bigmod(T p,T e,T M){
	LL ret = 1;
	for(; e > 0; e >>= 1){
		if(e & 1) ret = (ret * p) % M;
		p = (p * p) % M;
	} return (T)ret;
}
template <class T> inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template <class T> inline T modinverse(T a,T M){return bigmod(a,M-2,M);}

/*************************** END OF TEMPLATE ****************************/
const int N = 100;


int main()
{
      
      DI(tc);
      int cs= 0;
      while(tc--){
            LL a;
            scanf("%lld",&a);
            if(a==1){
                  printf("Case #%d: %d\n",  ++cs , 1);
                  continue;
            }
            printf("Case #%d: %lld\n", ++cs , bigmod(a,a-2,2000000011LL));
      }
      return 0;
}