2D BIT

2d bit is easier to code,
For 1d bit, query(x) return the sum of all the elements which index is <= x, index starting from 1
For 2d bit , query(x,y) return the sum of all the elements of the rectangle (1,1) to (x,y)

Practice Problem:Matsum

/*
 
 *************************
 Id  : Matrix.code
 Task:
 Date:
 
 **************************
 
 */
 
#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 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 = 2013;
Long bit[N][N];
int a[N][N];
void update(int x,int y,int val)
{
    for(int i= x; i< N ; i += i&-i) {
        for(int j = y; j < N; j += j&-j) {
            bit[i][j] += val;
        }
    }
}
Long query(int x,int y)
{
    Long r = 0;
    for(int i = x; i> 0; i-= i&-i ) {
        for(int j = y; j > 0; j-= j&-j ) {
            r += bit[i][j];
        }
    }
    return r;
}
char s[5];
int main()
{
 
    Di(t);
    while(t--){
        Di(n);
        forn(i,n+1) forn(j,n+1) bit[i][j] = 0 , a[i][j] = 0;
        while(scanf("%s",s)) {
            if(strcmp(s,"END") == 0 ) break;
            if(strcmp(s,"SET") == 0) {
                Diii(x,y,u);
                x++,y++;
                update(x,y,u - a[x][y]);
                a[x][y] = u;
            }
            if(strcmp(s,"SUM") == 0){
                Dii(x1,y1);
                Dii(x2,y2);
                x1 ++ ,y1 ++;
                x2 ++, y2 ++;
                printf("%lld\n", query(x2,y2) - query(x2,y1-1) - query(x1-1,y2) + query(x1-1,y1-1));
            }
        }
    }
}

SPOJ – CCOST

Discussion:
The First Intution that comes to mind after reading the problem is 2D BIT but if you see the memory requirement , you will be able to figure it out that the problem is not for 2D BIT. The problem can be solved by 1D BIT only.
Store all the Tree Updates and all the queries and sort both of them w.r.t to y cordinate. Mantain an BIT for the x-cordinate ( compress the Array to it’s Rank to maximum size of 10^5 instead of 10^7). Now Update the BIT and process the query simultaneously like this:
Now,For a particular y co-ordinate,
-> if it is updating a tree co-ordinate,then update(x,v)
-> if y is a query then query(x2) – query(x1), Range query

/*
 
 *************************
 Id  : Matrix.code
 Task:
 Date:
 
 **************************
 
 */

#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 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;}
template <class T> inline T bigmod(T p,T e,T M){Long 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);}
void io(){freopen("/Users/MyMac/Desktop/in.txt","r",stdin);}

/*************************** END OF TEMPLATE ****************************/
const int N = 5e5+5;
struct Event{
      int y,type,x1,x2,val;
      Event(int y,int type,int x1,int x2,int val):y(y),type(type),x1(x1),x2(x2) ,val(val){};
};
bool cmp(Event a,Event b)
{
      if(a.y==b.y){
            return a.type < b.type;
      }
      else return a.y<b.y;
}
Long bit[N];
void update(int x,int val)
{
      while(x<N) {
            bit[x]+=val;x+=x&-x;
      }
}
Long query(int x)
{
      Long r = 0;
      while(x>0)r+=bit[x],x-=x&-x;
      return r;
}

vector<Event> E;
vector<int> o;
int qq[N][2];
Long oo[N], ans[N];
int main()
{
      Di(t);
      while(t--) {
            Di(n);
            forn(i,n){
                  Diii(x,y,v);
                  o.pb(x);
                  E.pb(Event(y,0,x,-1,v));
            }
            Di(q);
            int cnt = 0;
            forn(i,q ){
                  Dii(x1,y1);
                  Dii(x2,y2);
                  o.pb(x2);
                  o.pb(x1-1);
                  
                  E.pb(Event(y1-1,1,x1-1,x2,cnt++));
                  E.pb(Event(y2,1,x1-1,x2,cnt++));
                  
            }
            sort(all(o));
            o.resize(unique(all(o)) - o.begin());
            sort(all(E),cmp);
            for(int i=0;i<E.Sz;i++){
                  Event it=E[i];
                  if(it.type==0) {
                        int  x1=lower_bound(o.begin(), o.end(), E[i].x1) - o.begin() + 1;
                        update(x1,E[i].val);
                  }
                  else {
                        int x2 = lower_bound(o.begin(), o.end(), E[i].x2) - o.begin() + 1;
                        int x1 = lower_bound(o.begin(), o.end(), E[i].x1) - o.begin() + 1;
                        oo[it.val] = query(x2)- query(x1);
                  }
                  
            }
             cnt = 0;
            forn(i,q){
                  ans[i] = oo[cnt+1] - oo[cnt];
                  cnt+=2;
            }
            forn(i,q) printf("%lld\n", ans[i]);
            E.clear();
            o.clear();
            ms(bit,0);
      }
      return 0;
}

519E CF

Link : Problem
Solution:

/*
 
 *************************
 Id  : Matrix.code
 Task:
 Date:
 
 **************************
 
 */

#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 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 = 1e5+5;
const int LG = 18;
int P[N][LG] , dep[N];
int Time[N] , dfn = 0;
vector<int> sub[N] , sib[N];
int sz[N];
vector<int>G[N];
int L[N], R[N];
void dfs(int u,int p,int lv = 0)
{
      Time[u] =++ dfn;
      dep[u]= lv;
      sz[u]=1;
      L[u] = dfn+1;
      for(auto a: G[u]) if(a!=p){
            P[a][0] = u;
            dfs(a,u,lv+1);
            sz[u] += sz[a];
            sub[u].pb(dfn);
            sib[u].pb(sz[a]);
      }
      R[u] = dfn;
}

int lca(int u,int v)
{
      if(dep[u] < dep[v]) swap(u,v);
      int d = dep[u] - dep[v];
      for(int i=LG-1;i >=0 ; i--) if(d&(1<<i)) u= P[u][i];
      if(u==v) return u;
      
      for(int i = LG-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];
      
}
int pth(int u,int p)
{
      //db(p);
      for(int i = LG-1; i>=0;i--) if(p&(1<<i)) u = P[u][i] , p-= (1<<i);
      return u;
}

int main()
{
      Di(n);
      forn(i,n-1) {
            Dii(a,b);
            G[a].pb(b);
            G[b].pb(a);
            
      }
      ms(P,-1);
      dfs(1,-1);
      for(int i=1;i<LG;i++){
            for(int j=1;j<=n ;j++ ) {
                  if(P[j][i-1] !=-1 ) P[j][i] = P[P[j][i-1]][i-1];
            }
      }
      
      Di(q);
      while(q--)
      {
            Dii(a,b);
            int o = dist(a,b);
            int pivot;
            if(o % 2==0 ) {
                  if(dep[a] > dep[b]) pivot= pth(a,o/2);
                  else pivot = pth(b,o/2);
                  int loo = lca(a,b);
                  
                  if(pivot == loo) {
                        int d = n;
                        if(Time[a] >= L[pivot] && Time[a] <= R[pivot]) {
                              int p1 = lower_bound(all(sub[pivot]),Time[a]) - sub[pivot].begin();
                              d -= sib[pivot][p1];
                        }
                        if(Time[b]>= L[pivot] && Time[b] <= R[pivot]) {
                              int p1 = lower_bound(all(sub[pivot]),Time[b]) - sub[pivot].begin();
                              d -= sib[pivot][p1];
                        }
                        printf("%d\n",d);
                  }
                  else {
                        int d = sz[pivot];
                        if(Time[a] >= L[pivot] && Time[a] <= R[pivot]) {
                              int p1 = lower_bound(all(sub[pivot]),Time[a]) - sub[pivot].begin();
                              d -= sib[pivot][p1];
                        }
                        if(Time[b]>= L[pivot] && Time[b] <= R[pivot]) {
                              int p1 = lower_bound(all(sub[pivot]),Time[b]) - sub[pivot].begin();
                              d -= sib[pivot][p1];
                        }
                        printf("%d\n",d);
                  }
                  
            }else printf("0\n");
            
      }
      
      
      
      return 0;
}

FFT UVA – 12298 – Super Poker II

Discussion: FFT Problem,
Represent S,H,D,C in polinomial, Then Fourier Transform, Multiply, Then inverse Fourier Transform

/*
 
 *************************
 Id  : Matrix.code
 Task:
 Date:
 
 **************************
 
 */

#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 all(x)                  (x).begin(),(x).end()
#define gc                      getchar_unlocked
#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;}
template <class T> inline T bigmod(T p,T e,T M){Long 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);}
void io(){freopen("/Users/MyMac/Desktop/in.txt","r",stdin);}

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

typedef long double T;
long double PI = acos(-1.0); // Without long double gives WA
struct Complex{ 
      T x,y;
      Complex(T x=0,T y=0):x(x),y(y){}
      Complex operator + (const Complex &a) const{return Complex(x+a.x,y+a.y);};
      Complex operator - (const Complex &a) const{return Complex(x-a.x,y-a.y);};
      Complex operator * (const Complex &a) const{return Complex(x*a.x-y*a.y,x*a.y+y*a.x);};
};

struct Fast_Fourier{
      Complex A[1 << 19];
      int rev(int id, int len)
      { // Reversed bit value , 011 -> 110
            int ret = 0;
            for(int i = 0; (1 << i) < len; i++){
                  ret <<= 1;
                  if(id & (1 << i)) ret |= 1;
            }
            return ret;
      }
      
      
      void FFT(Complex a[], int len, int DFT)
      {
            for(int i = 0; i < len; i++) A[rev(i, len)] = a[i];
            for(int s = 1; (1 << s) <= len; s++)
            {
                  int m = (1 << s);
                  Complex wm = Complex(cos(DFT*2*PI/m), sin(DFT*2*PI/m));
                  for(int k = 0; k < len; k += m)
                  {
                        Complex w = Complex(1, 0);
                        for(int j = 0; j < (m >> 1); j++)
                        {
                              Complex t = w*A[k + j + (m >> 1)];
                              Complex u = A[k + j];
                              A[k + j] = u + t;
                              A[k + j + (m >> 1)] = u - t;
                              w = w*wm;
                        }
                  }
            }
            if(DFT == -1) for(int i = 0; i < len; i++) A[i].x /= len, A[i].y /= len;
            for(int i = 0; i < len; i++) a[i] = A[i];
            return;
      }

}fft ;
Complex S[1 << 19], H[1 << 19], C[1 << 19], D[1 << 19];


bool vis[50005];
void seive()
{
      int MX = 5e4+4;
      for(int i= 2;i*i<MX; i++){
            if(vis[i]==0){
                  for(int j=2; i*j<MX ; j++ ) vis[i*j] = 1;
            }
      }
      
}
int main()
{
      int a, b, c;
      seive();
      while(scanf("%d %d %d", &a, &b, &c), a || b || c)
      {
            int len = 1;
            while(len <= b) len <<= 1;
            len <<= 3;
            for(int i = 0; i <= b; i++)
                  if(vis[i]) S[i] = H[i] = C[i] = D[i] = Complex(1, 0);
                  else S[i] = H[i] = C[i] = D[i] = Complex(0, 0);
            for(int i = b + 1; i < len; i++) S[i] = H[i] = C[i] = D[i] = Complex(0, 0);
            int num;
            char s;
            for(int i = 0; i < c; i++)
            {
                  scanf("%d%c", &num, &s);
                  if(s=='S') S[num] = Complex(0,0);
                  if(s=='H') H[num] = Complex(0,0);
                  if(s=='D') D[num] = Complex(0,0);
                  if(s=='C') C[num] = Complex(0,0);
            }
            fft.FFT(S, len, 1);
            fft.FFT(H, len, 1);
            fft.FFT(C, len, 1);
            fft.FFT(D, len, 1);
            for(int i = 0; i < len; i++)
                  S[i] = S[i]*H[i]*C[i]*D[i];
            fft.FFT(S, len, -1);
            for(int i = a; i <= b; i++) printf("%lld\n", (Long)(S[i].x + 0.5));
            puts("");
      }
      return 0;
}

Mincost Maxflow Implementation

Problem : Uva – 1317
Discussion:
Algorithm to solve:
Mincost Maxflow
Graph Construct:

1. for i,j,w , give i -> j+1, with capacity 1, cost -w
2. for i=0 to 355, give i->i+1, with capacity 2, cost 0
3. Calculate mincost Max flow, ans = – MincostMaxflow

/*
 
 *************************
 Id  : Matrix.code
 Task:
 Date:
 
 **************************
 
 */

#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 aT(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;}
template <class T> inline T bigmod(T p,T e,T M){Long 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);}
void io(){freopen("/Users/MyMac/Desktop/in.txt","r",stdin);}

/*************************** END OF TEMPLATE ****************************/
const int N = 370;
typedef long long T;

struct Edge {
      int  u , v ;
      T cap ,flow , cost;
};

struct MCMF {
      int n,m,s,t;      // Total Number of Node Including S,T
      vector<int> G[N];     //Graph
      vector<Edge> E;         // EdgeList
      T d[N];             // Distance Array of BeTmanFord
      bool inq[N];           // Is node in queue
      int p[N];
      int a[N];
      
      void init(T n){
            this->n =n;
            for(T i = 0; i < n ; i ++ ) G[i].clear();
            E.clear();
      }
      
      void addEdge( int u , int v , T cap , T cost ){
            E.push_back({u, v , cap , 0 , cost});       // Positive Cost
            E.push_back({v,u , 0, 0 , -cost } );        // Negative Cost
            m = E.size();
            G[u].push_back(m - 2);
            G[v].push_back(m - 1);
            
      }
      
      bool BelmanFord(T &flow , T &cost ) {
            
            for(int i = 0; i < n ;i  ++) d[i] = INF ;
            memset(inq, 0, sizeof(inq));
            d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = INF ;
            
            queue<int> Q;
            Q.push(s);
            while(!Q.empty() ) {
                  T u = Q.front(); Q.pop();
                  inq[u] = 0;

                  for( int i = 0 ; i < G[u].size() ; i ++ ) {
                        Edge &e = E[G[u][i]];
                        if( e.cap > e.flow && d[e.v] > d[u] + e.cost ) {
                              d[e.v] = d[u] + e.cost;
                              p[e.v] = G[u][i];
                              a[e.v] = min( a[u] , e.cap - e.flow );
                              
                              if( inq[e.v ] == 0 ) {
                                    Q.push(e.v);
                                    inq[e.v] = 1;
                              }
                        }
                  }
            }
            
            if( d[t] == INF ) return false;     // No augmenting Path
            flow = a[t];
            cost = d[t] ;               // Unit cost
            int u = t ;
            while( u  != s ) {
                  E[p[u]].flow += a[t];
                  E[p[u]^1].flow -= a[t];
                  u = E[p[u]].u;
                  
            }
            
            return true;
      }
      
      T Mincost(  int s, int  t ){
            this->s=s,this->t=t;
            T Mcost = 0;
            T Flow = 0;
            T f = 0 ;    // For Each CaT , The flow
            T d = 0;      // Shortest Distance / Cost Per Flow
            
            while( BelmanFord( f, d) ) {
                  Flow += f;
                  Mcost += f *d ;
            }
            
            return Mcost;
            
      }
} maxf;

int main()
{
      int n;
      while(scanf("%d",&n)==1 && n ) {
            maxf.init(370);
            forn(i,n) {
                  Diii(a,b,c);
                  maxf.addEdge(a,b+1,1,-c);
            }
            forn(i,366) {
                  maxf.addEdge(i,i+1,2,0);
            }
            int Source = 0, Sink = 366;
            T o = maxf.Mincost(Source,Sink);
            printf("%lld\n",-o);
      }
      return 0;
}


All Pair Maximum Flow

Problem : UVA – 11594
Solution : Gomory–Hu tree

Property :
1.The vertex set of the tree and the graph is the same.
2.The maximum flow between vertices u and v in the tree is equal to the maximum flow in the graph.

Using n maxflows, we can create Gomory–Hu tree
Total Complexity : O(n * T(maxflow))
Code :

/*
 
 *************************
 Id  : Matrix.code
 Task:
 Date:
 
 **************************
 
 */

#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 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;}
template <class T> inline T bigmod(T p,T e,T M){Long 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);}
void io(){freopen("/Users/MyMac/Desktop/in.txt","r",stdin);}

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

struct Edge{
      int u,v;
      Long cap,flow;
};
struct Dinic{
      int n,m,s,t;
      vector<int>G[N];
      vector<Edge>E;
      int cur[N];
      int d[N];
      bool vis[N];
      
      void init(int n)
      {
            this->n=n;
            forn(i,n+1) G[i].clear();
            E.clear();
      }
      
      void addEdge(int u,int v,Long cap)
      {
            E.push_back({u,v,cap,0});
            E.push_back({v,u,0,0});
            m = E.Sz;
            G[u].pb(m-2);
            G[v].pb(m-1);
      }
      
      bool bfs()
      {
            ms(vis,0);
            queue<int>q;
            q.push(s);
            vis[s]=1;
            d[s] = 0;
            while(!q.empty()){
                  int u = q.front() ; q.pop();
                  for(int i = 0; i < G[u].Sz;i ++ ) {
                        Edge &e = E[G[u][i]];
                        if(vis[e.v] == 0 && e.cap > e.flow) {
                              vis[e.v]  =1;
                              d[e.v] = 1 + d[u];
                              q.push(e.v);
                        }
                  }
            }
            return vis[t];
      }
      
      Long dfs(int u,Long oo)
      {
            if(u==t || oo == 0) return oo;
            Long Flow = 0, f;
            for(int &i = cur[u] ; i < G[u].Sz ; i ++ ) {
                  Edge &e= E[G[u][i]];
                  if(d[e.v] == 1 + d[u] && (f = dfs(e.v , min(oo  , e.cap - e.flow))) > 0 ){
                        e.flow += f;
                        E[G[u][i] ^1 ].flow -=f;
                        Flow += f;
                        oo-=f;
                        if(oo == 0 ) break;
                  }
            }
            return Flow;
            
      }
      
      Long dinitz(int s,int t)
      {
            this->s= s, this->t=t;
            Long Mf = 0;
            while(bfs()){
                  ms(cur,0);
                  Mf += dfs(s,1LL<<45);
            }
            return Mf;
      }
      vector<int> getCut()
      {
            vector<int>cut;
            for(int i = 0;i < E.Sz; i ++ ) {
                  Edge &e = E[i];
                  if(e.flow > 0 && e.cap == e.flow ) cut.pb(i);
            }
            return cut;
      }
      
      void clear()
      {
            for(int i = 0;i < m ;i ++ ) E[i].flow = 0;
      }
      
      
}MaxF;

int F[N];
Long Ans[N][N];
int e[N];
vector<ii> T[N];
int id;

void dfs(int u,int p ,Long flow )
{
      
      for(auto a: T[u]) if(a.Fr != p) {
            Ans[id][a.Fr] = min(flow, a.Sc);
            dfs(a.Fr, u, min(flow  , a.Sc ));
      }
}
int main()
{
      Di(t);
      int cs = 0;
      while(t--) {
            Di(n);
            MaxF.init(n);
            forn(i,n ) forn(j,n) {
                  Di(a);
                  if(a)MaxF.addEdge(i,j,a);
            }
            /**************** Construction of Gomory- tree ****************/
            forn(i,n) F[i] = 0; 
            for(int i=1;i<n;i++ ){
                  MaxF.clear();
                  e[i] = MaxF.dinitz(i,F[i]); // MaxFlow 
                  MaxF.bfs();
                  for(int j = i+1; j< n; j ++ ) {
                        if(MaxF.vis[j] && F[j] == F[i] ) F[j]= i; // S-T Cut
                  }
            }
            // New Graph Creation
            for(int i = 1; i< n; i ++ ) {
                  T[i].pb(mp(F[i],e[i]));
                  T[F[i]].pb(mp(i,e[i]));
            }
            /* *************** END ******************************************/
            forn(i,n) {
                  id = i;
                  dfs(i,-1, 1LL<<60 );
            }
            printf("Case #%d:\n",++cs);
            forn(i,n) {
                  forn(j,n){
                        if(j) printf(" ");
                        printf("%lld", Ans[i][j]);
                  }
                  printf("\n");
            }
            forn(i,n) T[i].clear();
            
      }
      return 0;
}


CF – 510E – Fox And Dinner

Category : MaxFlow
Discussion:
First finding is: if a + b is a prime, then one of them is an odd number, another is an even number. (that’s why we set 2 ≤ xi)

Then we could find: every odd number have exactly 2 even number as neighborhood, and every even number have exactly 2 odd number as neighborhood. And that means we need |#even| = |#odd| to have a solution.

So it looks like bipartite graph matching, but every element matched 2 elements. And in fact it can be handled by maxflow: For each odd number, we add a node on the left side and link it from source with capacity equals to 2, and for each even number, we add a node on the right side and link it to sink with capacity equals to 2. And if sum of two numbers is a prime number, we link them with capacity equals to 1.

Then we solve the max flow, it have solution if and only if maxflow = 2 * |#even|.

We can construct the answer(cycles) from the matches.

/*
 
 *************************
 Id  : Matrix.code
 Task:
 Date:
 
 **************************
 
 */

#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 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 = 405;



typedef Long T;

struct Edge{
      int u,v;
      T cap,flow;
      
};
struct Dinic{
      int n,m,s,t;
      vector<Edge>E;
      vi G[N];
      bool vis[N];
      int d[N];
      int cur[N];
      
      
      void init(int n)
      {
            this->n=n;
            forn(i,n+1) G[i].clear();
            E.clear();
      }
      void addEdge(int u,int v, T cap)
      {
            E.push_back({u,v,cap,0});
            E.push_back({v,u,0,0});
            m = E.Sz;
            G[u].pb(m-2);
            G[v].pb(m-1);
      }
      
      bool bfs()
      {
            ms(vis,0);
            d[s]=0;
            queue<int>q;
            q.push(s);
            vis[s] = 1;
            while(!q.empty()){
                  int u = q.front(); q.pop();
                  for(int i = 0;i < G[u].Sz; i ++ ) {
                        Edge &e = E[G[u][i]];
                        if(vis[e.v] == 0 && e.cap > e.flow ) {
                              vis[e.v] = 1;
                              d[e.v] = 1 + d[u];
                              q.push(e.v);
                        }
                  }
            }
            return vis[t];
      }
      
      T dfs(int u, T oo){
            if(oo == 0  || u == t) return oo;
            T Fl = 0, f;
            for(int &i = cur[u] ; i < G[u].Sz; i ++ ) {
                  Edge &e = E[G[u][i]];
                  if(d[e.v] == 1 + d[u] && (f = dfs(e.v, min(oo, e.cap - e.flow))) > 0 ) {
                        e.flow += f;
                        E[G[u][i] ^1 ].flow -= f;
                        Fl +=f ;
                        oo -= f;
                        if(oo == 0 ) break;
                  }
            }
            return Fl;
      }
      
      T dinitz(int s,int t)
      {
            this->s =  s , this->t=t;
            T Flow = 0;
            while(bfs()){
                  ms(cur,0);
                  T oo = dfs(s,INF);
                  
                  Flow += oo;
                  
            }
            return Flow;
      }
      
      
}MaxF;
const int MX = 2e4+5;
bool vis[MX];
vi Prime;
void seive()
{
      vis[0]=vis[1] = 1;
      for(int i=2 ; i < MX; i ++ ) {
            if(vis[i] == 0 ) {
                  Prime.pb(i);
                  for(int j= 2; i *j < MX ; j ++ ) {
                        vis[i*j] = 1;
                  }
            }
      }
      //forn(i,100) if(vis[i] == 0 ) printf("%d\n" , i);
}

struct info{
      int a,id;
      int node;
      info(){}
      info(int a,int id,int node):a(a),id(id),node(node){}
      
      
};
vector<info> odd,even;

vi nodes;

int Map[N];

void dfs(int u,int p)
{
      if(vis[u] ) return;
      vis[u] = 1;
      nodes.pb(Map[u]);
      for(int i = 0; i < MaxF.G[u].Sz ; i ++ ) {
            Edge e = MaxF.E[MaxF.G[u][i]];
            if((e.flow ==1 || e.flow == -1) && e.v != p) {
                  dfs(e.v,u);
                  return;
            }
      }
      
}


int main()
{
      seive();
      Di(n);
      int cnt = 1;
      for(int i = 1;i <= n;i ++ ) {
            Di(a);
            if(a%2) odd.pb(info(a,i,cnt++));
            else even.pb(info(a,i,cnt++));
            Map[cnt-1] = i;
      }
      if(odd.Sz != even.Sz) printf("Impossible\n");
      else {
            MaxF.init(n+2);
            int k = n / 2;
            int Source = 0, Sink= cnt+1;
            for(auto a: odd)  {
                  MaxF.addEdge(Source, a.node,2);
            }
            for(auto a: even ) {
                  MaxF.addEdge(a.node,Sink,2);
            }
            for(auto a: odd) {
                  for(auto b : even ) {
                        if(vis[a.a+b.a] == 0 ) {
                              MaxF.addEdge(a.node,b.node,1);
                        }
                  }
            }
            T o = MaxF.dinitz(Source, Sink);
            if( o == n ) {
                  int cnt = 0;
                  ms(vis,0);
                  vector<int> L[100];
                  for(auto a: odd) {
                        if(vis[a.node] == 0 ) {
                              dfs(a.node,-1);
                              L[cnt++] = nodes;
                              nodes.clear();
                        }
                        
                  }
                  
                  printf("%d\n", cnt);
                  forn(i,cnt){
                        printf("%ld", L[i].Sz);
                        for(auto p: L[i]) printf(" %d",p);
                        printf("\n");
                  }
            }
            else printf("Impossible\n");
      }
      return 0;
}

CF – 546E – Soldier and Traveling

Category : MaxFlow
Discussion From editorial:
Let’s build a flow network in following way:

Make a source.

Make a first group of vertices consisting of n vertices, each of them for one city.

Connect a source with ith vertex in first group with edge that has capacity ai.

Make a sink and second group of vertices in the same way, but use bi except for ai.

If there is a road between cities i and j or i = j. Make two edges, first should be connecting ith vertex from first group, and jth vertex from second group, and has infinity capacity. Second should be similar, but connect jth from first group and ith from second group.

Then find a maxflow, in any complexity.

If maxflow is equal to sum of ai and is equal to sum of bi, then there exists an answer. How can we get it? We just have to check how many units are we pushing through edge connecting two vertices from different groups.


/*
 
 *************************
 Id  : Matrix.code
 Task:
 Date:
 
 **************************
 
 */

#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 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 = 205;
typedef Long T;

struct Edge{
      int u,v;
      T cap,flow;
      
};
struct Dinic{
      int n,m,s,t;
      vector<Edge>E;
      vi G[N];
      bool vis[N];
      int d[N];
      int cur[N];
      
      
      void init(int n)
      {
            this->n=n;
            forn(i,n+1) G[i].clear();
            E.clear();
      }
      void addEdge(int u,int v, T cap)
      {
            E.push_back({u,v,cap,0});
            E.push_back({v,u,0,0});
            m = E.Sz;
            G[u].pb(m-2);
            G[v].pb(m-1);
      }
      
      bool bfs()
      {
            ms(vis,0);
            d[s]=0;
            queue<int>q;
            q.push(s);
            vis[s] = 1;
            while(!q.empty()){
                  int u = q.front(); q.pop();
                  for(int i = 0;i < G[u].Sz; i ++ ) {
                        Edge &e = E[G[u][i]];
                        if(vis[e.v] == 0 && e.cap > e.flow ) {
                              vis[e.v] = 1;
                              d[e.v] = 1 + d[u];
                              q.push(e.v);
                        }
                  }
            }
            return vis[t];
      }
      
      T dfs(int u, T oo){
            if(oo == 0  || u == t) return oo;
            T Fl = 0, f;
            for(int &i = cur[u] ; i < G[u].Sz; i ++ ) {
                  Edge &e = E[G[u][i]];
                  if(d[e.v] == 1 + d[u] && (f = dfs(e.v, min(oo, e.cap - e.flow))) > 0 ) {
                        e.flow += f;
                        E[G[u][i] ^1 ].flow -= f;
                        Fl +=f ;
                        oo -= f;
                        if(oo == 0 ) break;
                  }
            }
            return Fl;
      }
      
      T dinitz(int s,int t)
      {
            this->s =  s , this->t=t;
            T Flow = 0;
            while(bfs()){
                  ms(cur,0);
                  T oo = dfs(s,INF);
                 
                  Flow += oo;
                  
            }
            return Flow;
      }
      
      
}MaxF;


int a[N] , b[N];

int Ans[N][N];

int main()
{
      
      Dii(n,m);
      int Sum = 0;
      for(int i = 1;i <= n; i ++ ) {
            Si(a[i]); Sum += a[i];
      }
      int SS = 0;
      for(int i = 1;i <= n; i ++ )  Si(b[i]), SS += b[i];
      if(SS != Sum ) {
            printf("NO\n");
            return 0;
      }
      MaxF.init(2*n+2);
      while(m--) {
            Dii(a,b);
            MaxF.addEdge(a,b+n,INF);
            MaxF.addEdge(b,a+n,INF);
            
      }
      int Source = 0, Sink = 2*n+1;
      for(int i= 1; i<= n;i ++) {
            MaxF.addEdge(Source,i,a[i]);
      }
      for(int i = 1;i <=n ;i ++ ) {
            MaxF.addEdge(i+n, Sink , b[i]);
      }
      for(int i = 1; i<= n;i ++ ) {
            MaxF.addEdge(i,i+n,INF);
      }
      T o = MaxF.dinitz(Source, Sink);
      if(o== Sum ) {
            printf("YES\n");
            
            for(int i = 1; i<= n;i ++ ) {
                  for(int j = 0; j < MaxF.G[i].Sz; j ++ ) {
                        Edge e = MaxF.E[MaxF.G[i][j]];
                        if(e.flow > 0 )Ans[i][e.v- n] = e.flow;
                        
                  }
            }
            for(int i= 1; i <= n; i ++ ) {
                  for(int j = 1;j <= n; j ++ ) printf("%d ", Ans[i][j]);
                  printf("\n");
            }
      }else printf("NO\n");
      return 0;
}

CF – 594D – REQ

Discussion:
The problem is a good data structure problem on offline query.
Using formula: phi(n) = n * (1 – 1/ p1) * ( 1 – 1/p2 ) ……

/*
 
 *************************
 Id  : Matrix.code
 Task: CF 594D
 Date:
 
 **************************
 
 */

#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 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;
const int MX= 1e6+6;
Long MOD = 1e9+7;
Long a[N];
vector<ii> G[N];
vector<int> Prime;
vector<int> L[MX];
bool vis[MX];


void seive()
{
      
      for(int i=2;i < MX ; i ++ ) {
            if(vis[i] ==0 ) {
                  L[i].pb(i);
                  Prime.pb(i);
                  for(int j = 2 ; i * j < MX ; j ++ ){
                        L[i*j].pb(i);
                        vis[i*j] = 1;
                  }
            }
      }
}

int pos[MX];
vector<ii> nxt[N];
Long ib[N];

void update(int x,Long val)
{
      while(x<N) {
            ib[x] *= val;
            ib[x] %= MOD;
            x += x&-x;
      }
}

Long ans[N];

Long query(int x)
{
      Long r  = 1;
      for( ; x > 0; x -= x&-x){
            r *= ib[x];
            r %= MOD;
      }
      return r;
}
int main()
{
      
      seive();
      Di(n);
      for(int i = 1;i <= n; i ++){
            Si(a[i]);
      }
      forn(i,MX) pos[i] = n+1;
      for(int i = n ; i>  0; i -- ) {
            for(auto k: L[a[i]]) {
                  nxt[i].pb(mp(k,pos[k]));
                  pos[k] = i;
            }
      }
      forn(i,n+1) ib[i] = 1;
      for(int i = 1;i <= n;i ++ ) update(i , a[i]);
      for(auto a: Prime ) {
            int posi = pos[a];
            if(posi <= n ) {
                  Long u = ((a-1) * modinverse(a,MOD)) % MOD;
                  update(posi,u);
            }
      }
      
      Di(q);
      
      forn(i,q){
            Dii(a,b);
            G[a].pb(mp(b,i));
      }
      for(int i = 1; i<= n; i ++ ) {
            for(auto a: G[i]) {
                  int R = a.Fr, ind = a.Sc;
                  ans[ind] = query(R);
            }
            update(i, modinverse(a[i] , MOD));
            for(int u = 0; u < L[a[i]].Sz; u ++ ) {
                  Long pp = L[a[i]][u];
                  Long up = (pp * modinverse(pp-1, MOD)) %MOD;
                  update(i,up);
                  int neid = nxt[i][u].Sc;
                  if(neid <= n ) {
                        up = ((pp-1) * modinverse(pp,MOD)) %MOD;
                        update(neid, up);
                  }
            }
      }
      forn(i,q) printf("%lld\n" , ans[i]);
      return 0;
}

Geometry Template


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

double INF = 1e100;
double EPS = 1e-12;


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

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

// 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;
}
// determine if lines from a to b and c to d are parallel or collinear
bool IsLP(PT a, PT b, PT c, PT d) {
      return fabs(cross(b-a, c-d)) < EPS;
}

bool IsLC(PT a, PT b, PT c, PT d) {
      return IsLP(a, b, c, d)
      && fabs(cross(a-b, a-c)) < EPS
      && fabs(cross(c-d, c-a)) < EPS;
}

// determine if line segment from a to b intersects with
// line segment from c to d
bool SGIN(PT a, PT b, PT c, PT d) {
      if (IsLC(a, b, c, d)) {
            if (dist2(a, c) < EPS || dist2(a, d) < EPS ||
                dist2(b, c) < EPS || dist2(b, d) < EPS) return true;
            if (dot(c-a, c-b) > 0 && dot(d-a, d-b) > 0 && dot(c-b, d-b) > 0)
                  return false;
            return true;
      }
      if (cross(d-a, b-a) * cross(c-a, b-a) > 0) return false;
      if (cross(a-c, d-c) * cross(b-c, d-c) > 0) return false;
      return true;
}
// compute intersection of line passing through a and b
// with line passing through c and d, assuming that unique
// intersection exists; for segment intersection, check if
// segments intersect first
PT LLIN(PT a, PT b, PT c, PT d) {
      b=b-a; d=c-d; c=c-a;
      assert(dot(b, b) > EPS && dot(d, d) > EPS);
      return a + b*cross(c, d)/cross(b, d);
}

// compute center of circle given three points
PT CCC(PT a, PT b, PT c) {
      b=(a+b)/2;
      c=(a+c)/2;
      return LLIN(b, b+RotCW90(a-b), c, c+RotCW90(a-c));
}

// determine if point is in a possibly non-convex polygon (by William
// Randolph Franklin); returns 1 for strictly interior points, 0 for
// strictly exterior points, and 0 or 1 for the remaining points.
// Note that it is possible to convert this into an *exact* test using
// integer arithmetic by taking care of the division appropriately
// (making sure to deal with signs properly) and then by writing exact
// tests for checking point on polygon boundary
bool PIPoly(const vector<PT> &p, PT q) {
      bool c = 0;
      for (int i = 0; i < p.size(); i++){
            int j = (i+1)%p.size();
            if (((p[i].y <= q.y && q.y < p[j].y) ||
                 (p[j].y <= q.y && q.y < p[i].y)) &&
                q.x < p[i].x + (p[j].x - p[i].x) * (q.y - p[i].y) / (p[j].y - p[i].y))
                  c = !c;
      }
      return c;
}

// determine if point is on the boundary of a polygon
bool POPoly(const vector<PT> &p, PT q) {
      for (int i = 0; i < p.size(); i++)
            if (dist2(PPS(p[i], p[(i+1)%p.size()], q), q) < EPS)
                  return true;
      return false;
}

// 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;
}

// compute intersection of circle centered at a with radius r
// with circle centered at b with radius R
vector<PT> CCIN(PT a, PT b, double r, double R) {
      vector<PT> ret;
      double d = sqrt(dist2(a, b));
      if (d > r+R || d+min(r, R) < max(r, R)) return ret;
      double x = (d*d-R*R+r*r)/(2*d);
      double y = sqrt(r*r-x*x);
      PT v = (b-a)/d;
      ret.push_back(a+v*x + RotCCW90(v)*y);
      if (y > 0)
            ret.push_back(a+v*x - RotCCW90(v)*y);
      return ret;
}

// This code computes the area or centroid of a (possibly nonconvex)
// polygon, assuming that the coordinates are listed in a clockwise or
// counterclockwise fashion.  Note that the centroid is often known as
// the "center of gravity" or "center of mass".
double ComputeSignedArea(const vector<PT> &p) {
      double area = 0;
      for(int i = 0; i < p.size(); i++) {
            int j = (i+1) % p.size();
            area += p[i].x*p[j].y - p[j].x*p[i].y;
      }
      return area / 2.0;
}

double CAR(const vector<PT> &p) {
      return fabs(ComputeSignedArea(p));
}

PT CCN(const vector<PT> &p) {
      PT c(0,0);
      double scale = 6.0 * ComputeSignedArea(p);
      for (int i = 0; i < p.size(); i++){
            int j = (i+1) % p.size();
            c = c + (p[i]+p[j])*(p[i].x*p[j].y - p[j].x*p[i].y);
      }
      return c / scale;
}

// tests whether or not a given polygon (in CW or CCW order) is simple
bool IsSimple(const vector<PT> &p) {
      for (int i = 0; i < p.size(); i++) {
            for (int k = i+1; k < p.size(); k++) {
                  int j = (i+1) % p.size();
                  int l = (k+1) % p.size();
                  if (i == l || j == k) continue;
                  if (SGIN(p[i], p[j], p[k], p[l]))
                        return false;
            }
      }
      return true;
}





// Uses Stanford Handnote