#include <cstdio>
#include <algorithm>
#include <vector>
#include <cmath>

#define FOR(a,b,c) for(int a=(b),_for=(c);a<_for;++a)
#define END(a) {printf ("%d ",a);return 0;}
#define ll long long
#define ull unsigned long long
#define lf double
#define x first
#define y second
#define pb push_back
#define mp make_pair
#define pii pair < int, int >

using namespace std;

const int MAXN = 4000;
const int MOD = 1000000007;
const int INF = ((1<<31)-1);

ll x,y;

ll sol;

ll cnt[3][3];
int GCD[MAXN+5][MAXN+5];

bool p(pii a,pii b,pii c){
	return abs(a.x*(b.y-c.y)+b.x*(c.y-a.y)+c.x*(a.y-b.y))%2;
}

ll f(int bm){
	ll ret=1;
	ret=ret*cnt[!!(bm&8)][!!(bm&1)]%MOD;
	ret=ret*cnt[!!(bm&16)][!!(bm&2)]%MOD;
	ret=ret*cnt[!!(bm&32)][!!(bm&4)]%MOD;
	return ret;
}

int gcd(int a,int b){
	if (GCD[a][b]) return GCD[a][b];
	if (!a) return GCD[a][b]=b;
	return GCD[a][b]=gcd(b,a%b);
}

int main(){
	scanf ("%I64d%I64d",&x,&y);
	FOR(i,0,x+1)
		FOR(j,0,y+1)
			cnt[i&1][j&1]++;
	FOR(bm,0,1<<6){
		pii a,b,c;
		c=mp(!!(bm&8),!!(bm&1));
		b=mp(!!(bm&16),!!(bm&2));
		a=mp(!!(bm&32),!!(bm&4));
		if (!p(a,b,c))
			sol=(sol+f(bm))%MOD;
	}
	sol-=(x+1)*(y+1);
	sol-=3ll*(x+1)*(y+1)*((x+1)*(y+1)-1)%MOD;
	FOR(i,0,x+2)
		FOR(j,0,y+2)
			GCD[i][j]=gcd(i,j);
	FOR(dx,0,x+1)
		FOR(dy,dx?-y:1,y+1){
			if (!dx && !dy) continue;
			ll num = GCD[dx][abs(dy)]-1;
			sol = (sol - 6*num*(x-abs(dx)+1)*(y-abs(dy)+1))%MOD;
		}
	sol = (sol+MOD)%MOD;
	printf ("%I64d",sol);

	return 0;
}


#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;

typedef long long LL;
const LL Mod=1000000007;
const LL MAX=10000+10;

LL w,h;
LL sum[MAX],g[MAX][MAX],f[MAX][MAX];

LL gcd(LL a,LL b)
{
	if(!b)return a;
	return gcd(b,a%b);
}

LL chaji(LL a,LL b,LL c,LL d,LL e,LL f)
{
	return (c-a)*(f-b)-(e-a)*(d-b);
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.txt","r",stdin);freopen("output.txt","w",stdout);
#endif
	LL i,j,k,a,b,c,ans=0;
	cin>>w>>h;
	for(i=0;i<=w;++i)
		for(j=0;j<=h;++j)
			++sum[(i%2)*2+(j%2)];
	for(i=0;i<4;++i)
		for(j=0;j<4;++j)
			for(k=0;k<4;++k)
			{
				if((chaji(i/2,i%2,j/2,j%2,k/2,k%2))%2==0)
				{
					a=sum[i];b=sum[j];c=sum[k];
					if(i==j && j==k)
						b-=1,c-=2;
					else if(i==j)
						--b;
					else if(i==k)
						--c;
					else if(k==j)
						--c;
					ans=(ans+a*b%Mod*c%Mod)%Mod;
				}
			}
	for(i=1;i<=w;++i)
		for(j=1;j<=h;++j)
		{
			LL p=gcd(i,j)-1;
			g[i][j]=(g[i-1][j]+g[i][j-1]+Mod-g[i-1][j-1] + (p>0)*p *6 )%Mod;
			f[i][j]=(f[i][j-1]+f[i-1][j]-f[i-1][j-1]+Mod+g[i][j]*2)%Mod;
		}
//	cout<<f[w][h]<<endl;
//	cout<<(ans-f[w][h]+Mod)%Mod<<" "<<(ans-f[w][h]%Mod+Mod)%Mod<<endl;
	ans=(ans-f[w][h]+Mod)%Mod;
	if(w+1>=3)
		ans=(ans+Mod-(w+1)*w%Mod*(w-1)%Mod*(h+1)%Mod)%Mod;
	if(h+1>=3)
		ans=(ans+Mod-(h+1)*h%Mod*(h-1)%Mod*(w+1)%Mod)%Mod;
	cout<<ans<<endl;
}


#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;

int main() {
    int bit = 1 << 20, n;
    string s;
    cin >> n;
    for(int i = 20; i > 0; --i) {
        if(n & bit) {
            s += std::to_string(i);
            s += " ";
        }
        bit = bit >> 1;
    }
    cout << s;
    return 0;
}


#include <iostream>
#include <vector>

void main()
{
    std::vector<int> res;
    res.reserve(100);
    int n;
    std::cin >> n;
    for (; n > 0; --n) {
        res.push_back(1);
        while (res.size() > 1 && *(res.end() - 1) == *(res.end() - 2)) {
            *(res.end() - 2) += 1;
            res.pop_back();
        }
    }
    char* d = "";
    for (int v : res) {
        std::cout << d << v;
        d = " ";
    }
    std::cout << std::endl;
}


// Bismillahirrahmanirrahim
// AgriCoder IPB
#include <bits/stdc++.h>

using namespace std;

#define FOR(i, agri, coder) for (int i = (int)agri; i <= (int)coder; i++)
#define REP(agri,coder) for (int agri = 0; agri < (int)coder; agri++)
#define FOREACH(i,agricoder) for (typeof((agricoder).end()) i = (agricoder).begin(); i != (agricoder).end(); ++i)
#define RESET(agri,coder) memset(agri, coder, sizeof(agri))
#define pb push_back
#define mp make_pair
#define EPS 1e-9
#define INF 0x3F3F3F3F
#define NL printf("\n----------------------------\n")

typedef long long ll;
typedef unsigned long long ULL;
typedef pair<int,int> ii;
typedef vector<int> vi;
typedef vector<ii> vii;
typedef pair<ll,ll> PLL;

int arahbar[8] = {0,1,0,-1,1,1,-1,-1};
int arahkol[8] = {1,0,-1,0,1,-1,-1,1};
int kudabar[8] = {-2,-1,1,2, 2,1 , -1 ,-2};
int kudakol[8] = {1 ,2 ,2,1,-1,-2 , -2,-1};

template<typename T>
T getNum() {
   T res=0;
   char c;
   while(1)
   {
      c=getchar_unlocked();
      if(c==' ' || c=='\n') continue;
      else break;
   }
   bool negatif;
   if (c=='-') {
       negatif = true;
       res = 0;
   }
   else {
       res=c-'0';
       negatif = false;
   }
   while(1)
   {
      c=getchar_unlocked();
      if('0'<=c && c<='9') res=10*res + c-'0';
      else break;
   }
   if (negatif) res*=-1;
   return res;
}

// ================================  TEMPLATE ENDS HERE ================================================== //

#define MAXN 100005

vector<int> arr;

int main() {
//  freopen("in.in","r",stdin);
	int n = getNum<int>();
	REP(i,n){
		arr.pb(1);
		if(arr.size()>1){
			while(arr.size()>1){
				int len = arr.size();
				if(arr[len-1]==arr[len-2]){
					arr[len-2] ++;
					arr.pop_back();
				}else break;
			}
		}
	}

	printf("%d", arr[0]);
	FOR(i,1,arr.size()-1){
		printf(" %d", arr[i]);
	}
	printf("\n");
	return 0;
}

// Alhamdulillahirabbilalamin


#include <iostream>
using namespace std;

int main()
{
	int n;
	cin>> n;

	string s;
	while(n >= 2)
	{
		s += (n % 2) + '0';
		n /= 2;
	}
	s += n + '0';

	int y = 1 << ((int)s.size() - 1);

	reverse(s.begin(), s.end());
	for(int i = 0; i < s.size(); i ++)
	{
		if(s[i] == '1')
			cout<< y << " ";
		y /= 2;
	}

	cout<< endl;
}


#include <set>
#include <map>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iomanip>
#include <complex>
#include <iostream>
#include <algorithm>

#include <ctime>
#include <deque>
#include <bitset>
#include <cctype>
#include <utility>
#include <cassert>

#define FOR(i,a,b) for(int i=(a),_b=(b); i<=_b; i++)
#define FORD(i,a,b) for(int i=(a),_b=(b); i>=_b; i--)
#define REP(i,a) for(int i=0,_a=(a); i<_a; i++)
#define EACH(it,a) for(__typeof(a.begin()) it = a.begin(); it != a.end(); ++it)

#define DEBUG(x) { cout << #x << " = "; cout << (x) << endl; }
#define PR(a,n) { cout << #a << " = "; FOR(_,1,n) cout << a[_] << ' '; cout << endl; }
#define PR0(a,n) { cout << #a << " = "; REP(_,n) cout << a[_] << ' '; cout << endl; }

#define sqr(x) ((x) * (x))
using namespace std;

struct Edge {
    int u, v, c, f;
    int next;
};

struct MaxFlow {
    int n, s, t;
    vector< Edge > edges;
    vector<int> head, current, h, avail;
    vector<long long> excess;

    MaxFlow(int n) : n(n), head(n, -1), current(n, -1), h(n), avail(n), excess(n) {
        edges.clear();
    }

    void addEdge(int u, int v, int c, bool bi = false) {
        Edge xuoi = {u, v, c, 0, head[u]};
        head[u] = edges.size(); edges.push_back(xuoi);
        Edge nguoc = {v, u, bi ? c : 0, 0, head[v]};
        head[v] = edges.size(); edges.push_back(nguoc);
    }

    long long getFlow(int _s, int _t) {
        s = _s; t = _t;
        init();

        int now = 0;
        queue<int> qu[2];
        REP(x,n)
            if (x != s && x != t && excess[x] > 0)
                qu[now].push(x);

        globalLabeling();

        int cnt = 0;
        while (!qu[now].empty()) {
            while (!qu[1-now].empty()) qu[1-now].pop();

            while (!qu[now].empty()) {
                int x = qu[now].front(); qu[now].pop();
                while (current[x] >= 0) {
                    int p = current[x];
                    if (edges[p].c > edges[p].f && h[edges[p].u] > h[edges[p].v]) {
                        bool need = (edges[p].v != s && edges[p].v != t && !excess[edges[p].v]);
                        push(current[x]);
                        if (need) qu[1-now].push(edges[p].v);
                        if (!excess[x]) break;
                    }
                    current[x] = edges[current[x]].next;
                }

                if (excess[x] > 0) {
                    lift(x);
                    current[x] = head[x];
                    qu[1-now].push(x);
                    cnt++;
                    if (cnt == n) {
                        globalLabeling();
                        cnt=0;
                    }
                }
            }
            now = 1 - now;
        }
        return excess[t];
    }

private:
    void init() {
        REP(i,n) current[i] = head[i];

        int p = head[s];
        while (p >= 0) {
            edges[p].f = edges[p].c;
            edges[p^1].f -= edges[p].c;
            excess[edges[p].v] += edges[p].c;
            excess[s] -= edges[p].c;
            p = edges[p].next;
        }
        FOR(v,0,n-1) h[v] = 1;
        h[s] = n; h[t] = 0;
    }

    void push(int i) {
        long long delta = min(excess[edges[i].u], (long long) edges[i].c - edges[i].f);
        edges[i].f += delta; edges[i^1].f -= delta;
        excess[edges[i].u] -= delta;
        excess[edges[i].v] += delta;
    }

    void lift(int u) {
        int minH = 2 * n;
        int p = head[u];
        while (p>=0) {
            if (edges[p].c > edges[p].f)
                minH = min(minH, h[edges[p].v]);
            p = edges[p].next;
        }
        h[u] = minH + 1;
    }

    void globalLabeling() {
        REP(i,n) avail[i] = 1, h[i] = 0;
        h[s] = n; h[t] = 0;
        queue<int> q; q.push(t); avail[t] = false;

        while (!q.empty()) {
            int x = q.front(); q.pop();
            int p = head[x];
            while (p >= 0) {
                int pp = p^1;
                if (avail[edges[pp].u] && edges[pp].f < edges[pp].c) {
                    h[edges[pp].u] = h[x] + 1;
                    avail[edges[pp].u] = 0;
                    q.push(edges[pp].u);
                }
                p = edges[p].next;
            }
            if (q.empty() && avail[s]) {
                avail[s] = false;
                q.push(s);
            }
        }
        REP(x,n) current[x] = head[x];
    }
};

const int di[] = {-1,1,0,0};
const int dj[] = {0,0,-1,1};

int n, t, startx, starty;
char scientistMap[22][22], locationMap[22][22];
int d[22][22][22][22];

void bfs(int turn, int u, int v) {
    int curu = u, curv = v;
    queue<int> qu, qv;
    qu.push(u); qv.push(v);
    d[u][v][u][v] = 0;

    while (!qu.empty()) {
        u = qu.front(); qu.pop();
        v = qv.front(); qv.pop();

        REP(dir,4) {
            int uu = u + di[dir], vv = v + dj[dir];
            if (uu < 1 || uu > n || vv < 1 || vv > n || locationMap[uu][vv] == 'Y') continue;
            if (d[curu][curv][uu][vv] >= 0) continue;

            if (turn && d[startx][starty][uu][vv] >= 0 && d[curu][curv][u][v] + 1 > d[startx][starty][uu][vv]) continue;

            if (turn && d[startx][starty][uu][vv] >= 0 && d[curu][curv][u][v] + 1 == d[startx][starty][uu][vv]) {
                if (locationMap[uu][vv] >= '1' && locationMap[uu][vv] <= '9') {
                    d[curu][curv][uu][vv] = d[curu][curv][u][v] + 1;
                    continue;
                }
                continue;
            }

            d[curu][curv][uu][vv] = d[curu][curv][u][v] + 1;
            qu.push(uu);
            qv.push(vv);
        }
    }
}

int id[22][22];

int main() {
    while (cin >> n >> t) {
        FOR(i,1,n) FOR(j,1,n) cin >> scientistMap[i][j];
        FOR(i,1,n) FOR(j,1,n) cin >> locationMap[i][j];
        memset(d, -1, sizeof d);

        FOR(i,1,n) FOR(j,1,n) if (locationMap[i][j] == 'Z') {
            startx = i;
            starty = j;
            bfs(0, i, j);
        }

        int cur = 0;
        FOR(i,1,n) FOR(j,1,n) id[i][j] = ++cur;

        MaxFlow flow(n*n+2);
        FOR(i,1,n) FOR(j,1,n) {
            if (scientistMap[i][j] >= '1' && scientistMap[i][j] <= '9')
                flow.addEdge(0, id[i][j], scientistMap[i][j] - '0');
            if (locationMap[i][j] >= '1' && locationMap[i][j] <= '9')
                flow.addEdge(id[i][j], n*n+1, locationMap[i][j] - '0');
        }

        FOR(i,1,n) FOR(j,1,n) if (scientistMap[i][j] >= '1' && scientistMap[i][j] <= '9') {
            bfs(1, i, j);

            FOR(u,1,n) FOR(v,1,n) if (locationMap[u][v] >= '1' && locationMap[u][v] <= '9')
                if (d[i][j][u][v] >= 0 && d[i][j][u][v] <= t) {
                    flow.addEdge(id[i][j], id[u][v], min(locationMap[u][v] - '0', scientistMap[i][j] - '0'));
                }
        }
        cout << flow.getMaxFlow(0, n*n+1) << endl;
    }
    return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;

struct node{
    int r,c,t;

    node(){}

    node(int _r, int _c, int _t){
        r = _r; c = _c; t = _t;
    }
}cur;

struct flow_graph{
    int MAX_V,E,s,t,head,tail;
    int *cap,*to,*next,*last,*dist,*q,*now;

    flow_graph(){}

    flow_graph(int V, int MAX_E){
        MAX_V = V; E = 0;
        cap = new int[2*MAX_E], to = new int[2*MAX_E], next = new int[2*MAX_E];
        last = new int[MAX_V], q = new int[MAX_V];
        dist = new int[MAX_V], now = new int[MAX_V];
        fill(last,last+MAX_V,-1);
    }

    void add_edge(int u, int v, int uv){
        if(uv > 0){
            to[E] = v, cap[E] = uv, next[E] = last[u]; last[u] = E++;
            to[E] = u, cap[E] = 0, next[E] = last[v]; last[v] = E++;
        }
    }

    bool bfs(){
        fill(dist,dist+MAX_V,-1);
        head = tail = 0;

        q[tail] = t; ++tail;
        dist[t] = 0;

        while(head<tail){
            int v = q[head]; ++head;

            for(int e = last[v];e!=-1;e = next[e]){
                if(cap[e^1]>0 && dist[to[e]]==-1){
                    q[tail] = to[e]; ++tail;
                    dist[to[e]] = dist[v]+1;
                }
            }
        }

        return dist[s]!=-1;
    }

    int dfs(int v, int f){
        if(v==t) return f;

        for(int &e = now[v];e!=-1;e = next[e]){
            if(cap[e]>0 && dist[to[e]]==dist[v]-1){
                int ret = dfs(to[e],min(f,cap[e]));

                if(ret>0){
                    cap[e] -= ret;
                    cap[e^1] += ret;
                    return ret;
                }
            }
        }

        return 0;
    }

    int max_flow(int source, int sink){
        s = source; t = sink;
        int f = 0,df;

        while(bfs()){
            for(int i = 0;i < MAX_V;++i) now[i] = last[i];

            while(true){
                df = dfs(s,INT_MAX);
                if(df==0) break;
                f += df;
            }
        }

        return f;
    }
}G(2 + 10 * 10 * 62,10 * 10 * (4 * 60  + 6));

int main(){
    int n,t;

    scanf("%d %d",&n,&t);

    char M1[n][n],M2[n][n];

    for(int i = 0;i < n;++i) scanf("%s",M1[i]);
    for(int i = 0;i < n;++i) scanf("%s",M2[i]);

    int sr = 0,sc = 0;
    int dist[n][n];
    memset(dist,-1,sizeof(dist));

    for(int i = 0;i < n;++i)
        for(int j = 0;j < n;++j)
            if(M1[i][j] == 'Z')
                sr = i,sc = j;

    int dr[] = {-1,1,0,0};
    int dc[] = {0,0,-1,1};
    int r2,c2;

    queue<node> Q;
    Q.push(node(sr,sc,0));
    dist[sr][sc] = 0;

    while(!Q.empty()){
        cur = Q.front();
        Q.pop();

        for(int i = 0;i < 4;++i){
            r2 = cur.r + dr[i];
            c2 = cur.c + dc[i];

            if(r2 >= 0 && r2 < n && c2 >= 0 && c2 < n && dist[r2][c2] == -1 && M1[r2][c2] != 'Y' && M1[r2][c2] != 'Z'){
                dist[r2][c2] = dist[cur.r][cur.c] + 1;
                Q.push(node(r2,c2,cur.t + 1));
            }
        }
    }

    for(int i = 0;i < n;++i){
        for(int j = 0;j < n;++j){
            if(M1[i][j] >= '0' && M1[i][j] <= '9'){
                G.add_edge(0,1 + i * n + j,M1[i][j] - '0');
                G.add_edge(1 + (t + 1) * n * n + i * n + j,1 + (t + 2) * n * n,M2[i][j] - '0');
            }
        }
    }

    for(int i = 0;i <= t;++i){
        for(int j = 0;j < n;++j){
            for(int k = 0;k < n;++k){
                if((dist[j][k] == -1 || dist[j][k] >= i) && M1[j][k] >= '0' && M1[j][k] <= '9'){
                    G.add_edge(1 + i * n * n + j * n + k, 1 + (t + 1) * n * n + j * n + k,M2[j][k] - '0');

                    if(i < t && (dist[j][k] == -1 || dist[j][k] > i)){
                        for(int d = 0;d < 4;++d){
                            r2 = j + dr[d];
                            c2 = k + dc[d];

                            if(M1[r2][c2] >= '0' && M1[r2][c2] <= '9' && (dist[r2][c2] == -1 || dist[r2][c2] >= i + 1))
                                G.add_edge(1 + i * n * n + j * n + k,1 + (i + 1) * n * n + r2 * n + c2,900);
                        }
                    }
                }
            }
        }
    }

    printf("%d\n",G.max_flow(0,1 + n * n * (t + 2)));

    return 0;
}


#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <algorithm>
#include <bitset>
#include <deque>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>
#include <cassert>
#include <unordered_set>
#include <climits>
#include <iomanip>
#include <unordered_map>
using namespace std;
typedef vector<int> vi;
typedef pair<int,int> ii;
typedef long long ll;
#define mset(a,b) memset(a,b,sizeof a)
#define pb push_back
#define mp make_pair
typedef vector<ll> vll;
namespace dinic{
    struct edge{
        int to, rev, f, cap;
        edge(){}
        edge(int _t, int _r, int _f, int _c):to(_t), rev(_r), f(_f), cap(_c){}
    };
    const int maxn = 500;
    int nodes = maxn, src, des, dist[maxn], q[maxn], work[maxn];
    vector<edge> g[maxn];
    void play(){
        for(int e = 0; e < maxn; e++) g[e].clear();
    }
    void addEdge(int s, int t, int cap, int dir = 0){
        edge a = {t, (int)g[t].size(), 0, cap};
        edge b = {s, (int)g[s].size(), 0, dir};
        g[s].push_back(a);
        g[t].push_back(b);
    }
    bool bfs(){
        memset(dist, -1, sizeof dist);
        dist[src] = 0;
        int qt = 0;
        q[qt++] = src;
        for(int e = 0; e < qt; e++){
            int u = q[e];
            for(edge &v:g[u]){
                if(dist[v.to] < 0 && v.f < v.cap){
                    dist[v.to] = dist[u] + 1;
                    q[qt++] = v.to;
                }
            }
        }
        return dist[des] != -1;
    }
    int dfs(int u, int f){
        if(u == des) return f;
        for(int &i = work[u]; i < g[u].size(); i++){
            edge &e = g[u][i];
            if(e.cap <= e.f) continue;
            int v = e.to;
            if(dist[v] == dist[u]+1){
                int df = dfs(v, min(f, e.cap - e.f));
                if(df > 0){
                    e.f += df;
                    g[v][e.rev].f -= df;
                    return df;
                }
            }
        }
        return 0;
    }
    ll flow(int _src, int _des){
        src = _src;
        des = _des;
        ll ans = 0;
        while(bfs()){
            memset(work, 0, sizeof work);
            while(int delta = dfs(src, (1<<30)))
                ans += delta;
        }
        return ans;
    }
};
using namespace dinic;
const int maxn2 = 11;
char scien[maxn2][maxn2], capsu[maxn2][maxn2];
int infected[maxn2][maxn2], run[maxn2][maxn2];
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
int main(){
    int n, t; cin >> n >> t;
    for(int e = 0; e < n; e++) for(int f = 0; f < n; f++) cin >> scien[e][f];
    for(int e = 0; e < n; e++) for(int f = 0; f < n; f++) cin >> capsu[e][f];
    int ax, ay;
    for(int e = 0; e < n; e++) for(int f = 0; f < n; f++)
        if(scien[e][f] == 'Z') ax = e, ay = f;
    {
        queue<ii> q; q.push(mp(ax, ay));
        mset(infected, -1);
        infected[ax][ay] = 0;
        while(!q.empty()){
            ii cur = q.front(); q.pop();
            for(int e = 0; e < 4; e++){
                ii next = mp(cur.first + dx[e], cur.second + dy[e]);
                if(next.first < 0 || next.first == n || next.second < 0 || next.second == n) continue;
                if(infected[next.first][next.second] == -1 && scien[next.first][next.second] != 'Y')
                    infected[next.first][next.second] = infected[cur.first][cur.second] + 1,
                    q.push(next);
            }
        }
    }
    for(int e = 0; e < n; e++) for(int f = 0; f < n; f++) if(infected[e][f] == -1) infected[e][f] = 1<<20;
    int src = 3*(n+1)*(n+1), des = src+1;
    for(int e = 0; e < n; e++) for(int f = 0; f < n; f++) if(isnumber(scien[e][f]) && scien[e][f] != '0'){
        // printf("(%d, %d)\n", e, f);
        addEdge(src, e*n + f, scien[e][f] - '0');
        queue<ii> q; q.push(mp(e, f));
        mset(run, -1); run[e][f] = 0;
        while(!q.empty()){
            ii cur = q.front(); q.pop();
            for(int g = 0; g < 4; g++){
                ii next = mp(cur.first + dx[g], cur.second + dy[g]);
                if(next.first < 0 || next.first == n || next.second < 0 || next.second == n) continue;
                if(run[next.first][next.second] == -1
                && isnumber(scien[next.first][next.second])
                && run[cur.first][cur.second]+1 <= t){
                    if(infected[next.first][next.second] > run[cur.first][cur.second]+1){
                        run[next.first][next.second] = run[cur.first][cur.second]+1;
                        q.push(next);
                    }
                    if(infected[next.first][next.second] >= run[cur.first][cur.second]+1
                    && isnumber(capsu[next.first][next.second]) && capsu[next.first][next.second] != '0'){
                        addEdge(e*n+f, n*n + (next.first*n + next.second), 1<<20, 1<<20);
                        // printf("(%d, %d) -> (%d, %d)\n", e, f, next.first, next.second);
                    }
                }
            }
        }
    }
    for(int e = 0; e < n; e++) for(int f = 0; f < n; f++) if(isnumber(capsu[e][f]) && capsu[e][f] != '0')
        addEdge(n*n + (e*n + f), des, capsu[e][f] - '0');
    cout << flow(src, des) << endl;
    return 0;
}


#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <algorithm>
#include <bitset>
#include <deque>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <utility>
#include <vector>
#include <cassert>
#include <unordered_set>
#include <climits>
#include <iomanip>
#include <unordered_map>
#include <cstring>
using namespace std;
typedef vector<int> vi;
typedef pair<int,int> ii;
typedef long long ll;
#define mset(a,b) memset(a,b,sizeof a)
#define pb push_back
#define mp make_pair
typedef vector<ll> vll;
namespace dinic{
    struct edge{
        int to, rev, f, cap;
        edge(){}
        edge(int _t, int _r, int _f, int _c):to(_t), rev(_r), f(_f), cap(_c){}
    };
    const int maxn = 500;
    int nodes = maxn, src, des, dist[maxn], q[maxn], work[maxn];
    vector<edge> g[maxn];
    void play(){
        for(int e = 0; e < maxn; e++) g[e].clear();
    }
    void addEdge(int s, int t, int cap, int dir = 0){
        edge a = {t, (int)g[t].size(), 0, cap};
        edge b = {s, (int)g[s].size(), 0, dir};
        g[s].push_back(a);
        g[t].push_back(b);
    }
    bool bfs(){
        memset(dist, -1, sizeof dist);
        dist[src] = 0;
        int qt = 0;
        q[qt++] = src;
        for(int e = 0; e < qt; e++){
            int u = q[e];
            for(edge &v:g[u]){
                if(dist[v.to] < 0 && v.f < v.cap){
                    dist[v.to] = dist[u] + 1;
                    q[qt++] = v.to;
                }
            }
        }
        return dist[des] != -1;
    }
    int dfs(int u, int f){
        if(u == des) return f;
        for(int &i = work[u]; i < g[u].size(); i++){
            edge &e = g[u][i];
            if(e.cap <= e.f) continue;
            int v = e.to;
            if(dist[v] == dist[u]+1){
                int df = dfs(v, min(f, e.cap - e.f));
                if(df > 0){
                    e.f += df;
                    g[v][e.rev].f -= df;
                    return df;
                }
            }
        }
        return 0;
    }
    ll flow(int _src, int _des){
        src = _src;
        des = _des;
        ll ans = 0;
        while(bfs()){
            memset(work, 0, sizeof work);
            while(int delta = dfs(src, (1<<30)))
                ans += delta;
        }
        return ans;
    }
};
using namespace dinic;
const int maxn2 = 11;
char scien[maxn2][maxn2], capsu[maxn2][maxn2];
int infected[maxn2][maxn2], run[maxn2][maxn2];
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
int main(){
    int n, t; cin >> n >> t;
    for(int e = 0; e < n; e++) for(int f = 0; f < n; f++) cin >> scien[e][f];
    for(int e = 0; e < n; e++) for(int f = 0; f < n; f++) cin >> capsu[e][f];
    int ax, ay;
    for(int e = 0; e < n; e++) for(int f = 0; f < n; f++)
        if(scien[e][f] == 'Z') ax = e, ay = f;
    {
        queue<ii> q; q.push(mp(ax, ay));
        mset(infected, -1);
        infected[ax][ay] = 0;
        while(!q.empty()){
            ii cur = q.front(); q.pop();
            for(int e = 0; e < 4; e++){
                ii next = mp(cur.first + dx[e], cur.second + dy[e]);
                if(next.first < 0 || next.first == n || next.second < 0 || next.second == n) continue;
                if(infected[next.first][next.second] == -1 && scien[next.first][next.second] != 'Y')
                    infected[next.first][next.second] = infected[cur.first][cur.second] + 1,
                    q.push(next);
            }
        }
    }
    for(int e = 0; e < n; e++) for(int f = 0; f < n; f++) if(infected[e][f] == -1) infected[e][f] = 1<<20;
    int src = 3*(n+1)*(n+1), des = src+1;
    for(int e = 0; e < n; e++) for(int f = 0; f < n; f++) if(isnumber(scien[e][f]) && scien[e][f] != '0'){
        // printf("(%d, %d)\n", e, f);
        addEdge(src, e*n + f, scien[e][f] - '0');
        queue<ii> q; q.push(mp(e, f));
        mset(run, -1); run[e][f] = 0;
        while(!q.empty()){
            ii cur = q.front(); q.pop();
            for(int g = 0; g < 4; g++){
                ii next = mp(cur.first + dx[g], cur.second + dy[g]);
                if(next.first < 0 || next.first == n || next.second < 0 || next.second == n) continue;
                if(run[next.first][next.second] == -1
                && isnumber(scien[next.first][next.second])
                && run[cur.first][cur.second]+1 <= t){
                    if(infected[next.first][next.second] > run[cur.first][cur.second]+1){
                        run[next.first][next.second] = run[cur.first][cur.second]+1;
                        q.push(next);
                    }
                    if(infected[next.first][next.second] >= run[cur.first][cur.second]+1
                    && isnumber(capsu[next.first][next.second]) && capsu[next.first][next.second] != '0'){
                        addEdge(e*n+f, n*n + (next.first*n + next.second), 1<<20, 1<<20);
                        // printf("(%d, %d) -> (%d, %d)\n", e, f, next.first, next.second);
                    }
                }
            }
        }
    }
    for(int e = 0; e < n; e++) for(int f = 0; f < n; f++) if(isnumber(capsu[e][f]) && capsu[e][f] != '0')
        addEdge(n*n + (e*n + f), des, capsu[e][f] - '0');
    cout << flow(src, des) << endl;
    return 0;
}


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

#define ms(s, n) memset(s, n, sizeof(s))
#define FOR(i, a, b) for (int i = (a); i < (b); i++)
#define FORd(i, a, b) for (int i = (a) - 1; i >= (b); i--)
#define FORall(it, a) for (__typeof((a).begin()) it = (a).begin(); it != (a).end(); it++)
#define sz(a) int((a).size())
#define present(t, x) (t.find(x) != t.end())
#define all(a) (a).begin(), (a).end()
#define uni(a) (a).erase(unique(all(a)), (a).end())
#define pb push_back
#define pf push_front
#define mp make_pair
#define fi first
#define se second
#define prec(n) fixed<<setprecision(n)
#define bit(n, i) (((n) >> (i)) & 1)
#define bitcount(n) __builtin_popcountll(n)
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int> pi;
typedef vector<int> vi;
typedef vector<pi> vii;
const int MOD = (int) 1e9 + 7;
const int INF = (int) 1e9;
const ll LINF = (ll) 1e18;
const ld PI = acos((ld) -1);
const ld EPS = 1e-9;
inline ll gcd(ll a, ll b) {ll r; while (b) {r = a % b; a = b; b = r;} return a;}
inline ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
inline ll fpow(ll n, ll k, int p = MOD) {ll r = 1; for (; k; k >>= 1) {if (k & 1) r = r * n % p; n = n * n % p;} return r;}
template<class T> inline int chkmin(T& a, const T& val) {return val < a ? a = val, 1 : 0;}
template<class T> inline int chkmax(T& a, const T& val) {return a < val ? a = val, 1 : 0;}
inline ll isqrt(ll k) {ll r = sqrt(k) + 1; while (r * r > k) r--; return r;}
inline ll icbrt(ll k) {ll r = cbrt(k) + 1; while (r * r * r > k) r--; return r;}
inline void addmod(int& a, int val, int p = MOD) {if ((a = (a + val)) >= p) a -= p;}
inline void submod(int& a, int val, int p = MOD) {if ((a = (a - val)) < 0) a += p;}
inline int mult(int a, int b, int p = MOD) {return (ll) a * b % p;}
inline int inv(int a, int p = MOD) {return fpow(a, p - 2, p);}
inline int sign(ld x) {return x < -EPS ? -1 : x > +EPS;}
inline int sign(ld x, ld y) {return sign(x - y);}
#define db(x) cout << #x << " = " << (x) << "\n";

const int maxn = 75 + 1;
int n;
string s;
int nV, nK, nX;
int posV[maxn];
int posK[maxn];
int posX[maxn];
int dp[maxn][maxn][maxn][3];

int calc(int V, int K, int X, int lst) {
	if (V + K + X == n) return 0;
	int& res = dp[V][K][X][lst];
	if (~res) return res;
	res = INF;
	if (V < nV) {
		int cost = max(0LL, upper_bound(posK, posK + nK, posV[V]) - posK - K);
		cost += max(0LL, upper_bound(posX, posX + nX, posV[V]) - posX - X);
		chkmin(res, calc(V + 1, K, X, 0) + cost);
	}
	if (K < nK && lst) {
		int cost = max(0LL, upper_bound(posV, posV + nV, posK[K]) - posV - V);
		cost += max(0LL, upper_bound(posX, posX + nX, posK[K]) - posX - X);
		chkmin(res, calc(V, K + 1, X, 1) + cost);
	}
	if (X < nX) {
		int cost = max(0LL, upper_bound(posV, posV + nV, posX[X]) - posV - V);
		cost += max(0LL, upper_bound(posK, posK + nK, posX[X]) - posK - K);
		chkmin(res, calc(V, K, X + 1, 2) + cost);
	}
	return res;
}

void solve() {
	cin >> n >> s;
	FOR(i, 0, n) {
		if (s[i] == 'V') {
			posV[nV++] = i;
		}
		else if (s[i] == 'K') {
			posK[nK++] = i;
		}
		else {
			posX[nX++] = i;
		}
	}
	ms(dp, -1);
	cout << calc(0, 0, 0, 2) << "\n";
}

int main() {
	ios_base::sync_with_stdio(0); //cin.tie(0);
#ifdef _LOCAL_
	freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout);
#endif
	solve();
#ifdef _LOCAL_
	//printf("\nTime elapsed: %dms", 1000 * clock() / CLOCKS_PER_SEC);
#endif
	return 0;
}


#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <limits>
#include <string>
#include <cassert>

using namespace std;

typedef long long LL;
typedef vector < int > VI;
typedef pair < int,int > II;
typedef vector < II > VII;
const int MOD = 1e9+7;
inline int mult(int a , int b) { LL x = a; x *= LL(b); if(x >= MOD) x %= MOD; return x; }
inline int add(int a , int b) { return a + b >= MOD ? a + b - MOD : a + b; }
inline int sub(int a , int b) { return a - b < 0 ? MOD - b + a : a - b; }
LL powmod(LL a,LL b) { if(b==0)return 1; LL x=powmod(a,b/2); LL y=(x*x)%MOD; if(b%2) return (a*y)%MOD; return y%MOD; }

const int inf = 1e9 + 7;
string s;
int n;
int dp[80][80][80][2];
int getV(int cur, int nv, int nk, int nx) {
  int ck = 0, cv = 0, cx = 0;
  for(int i = 0; i < n; i ++) {
    if(cv == nv && s[i] == 'V') {
      int extra = max(0,nk-ck) + max(0,nx-cx);
      return extra + i - cur;
    }
    if(s[i] == 'K')
      ck ++;
    else if(s[i] == 'V')
      cv ++;
    else
      cx ++;
  }
  return inf;
}
int getK(int cur, int nv, int nk, int nx) {
  int ck = 0, cv = 0, cx = 0;
  for(int i = 0; i < n; i ++) {
    if(ck == nk && s[i] == 'K') {
      int extra = max(0,nv-cv) + max(0,nx-cx);
      return extra + i - cur;
    }
    if(s[i] == 'K')
      ck ++;
    else if(s[i] == 'V')
      cv ++;
    else
      cx ++;
  }
  return inf;
}
int getX(int cur, int nv, int nk, int nx) {
  int ck = 0, cv = 0, cx = 0;
  for(int i = 0; i < n; i ++) {
    if(cx == nx && (s[i] != 'V' && s[i] != 'K')) {
      int extra = max(0,nk-ck) + max(0,nv-cv);
      return extra + i - cur;
    }
    if(s[i] == 'K')
      ck ++;
    else if(s[i] == 'V')
      cv ++;
    else
      cx ++;
  }
  return inf;
}
int go(int nv, int nk, int nx, bool isv) {
  if(nv + nk + nx == n) return 0;
  if(dp[nv][nk][nx][isv] != -1)
    return dp[nv][nk][nx][isv];
  int ret = inf;
  int cur = nv + nk + nx;
  ret = min(ret, go(nv+1, nk, nx, 1) + getV(cur, nv, nk, nx));
  ret = min(ret, go(nv, nk, nx+1, 0) + getX(cur, nv, nk, nx));
  if(!isv)
    ret = min(ret, go(nv, nk+1, nx, 0) + getK(cur, nv, nk, nx));
  return dp[nv][nk][nx][isv] = ret;
}
int main() {
  memset(dp,-1,sizeof(dp));
  cin >> n;
  cin >> s;
  cout << go(0,0,0,0) << endl;
  return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define REP(i,j,k) for(register int (i)=(j);(i)<(k);++(i))

struct pfx{int s[3];};
int operator-(pfx x,pfx y){
	int ret=0;
	REP(i,0,3)ret+=max(0LL,x.s[i]-y.s[i]);
	return ret;
}

const int maxn=80;
const int inf=1ll<<50;
int n,dp[maxn][maxn][maxn][3];
char s[maxn],t[maxn];
pfx vkx[3][maxn];

inline void MIN(int&x,int y){x=min(x,y);}

main(){
	cin.tie(0),cout.tie(0),ios_base::sync_with_stdio(false);
	cin>>n;
	pfx tt;tt.s[0]=tt.s[1]=tt.s[2]=0;
	REP(i,0,n){
		char c;int x;
		cin>>c,x=(c=='V'?0:c=='K'?1:2);
		++tt.s[x],vkx[x][tt.s[x]]=tt;
	}
	REP(v,0,n+1)REP(k,0,n+1)REP(x,0,n+1)REP(i,0,3)dp[v][k][x][i]=inf;
	dp[0][0][0][2]=0;
	REP(v,0,n)REP(k,0,n)REP(x,0,n){
		if(v+k+x>=n)continue;
		REP(i,0,3)REP(j,0,3)if(!(i==0&&j==1)){
			pfx nn;nn.s[0]=v+(j==0),nn.s[1]=k+(j==1),nn.s[2]=x+(j==2);
			if(nn.s[0]>tt.s[0]||nn.s[1]>tt.s[1]||nn.s[2]>tt.s[2])continue;
			MIN(dp[nn.s[0]][nn.s[1]][nn.s[2]][j],dp[v][k][x][i]+(nn-vkx[j][nn.s[j]]));
		}
	}
	int mn=inf;
	REP(i,0,3)mn=min(mn,dp[tt.s[0]][tt.s[1]][tt.s[2]][i]);
	cout<<mn<<'\n';
}


#include<bits/stdc++.h>
using namespace std;
mt19937 rng(chrono::system_clock::now().time_since_epoch().count());
mt19937_64 rngll(rng());
typedef long long ll;
typedef pair<int,int>pii;
typedef pair<int,ll>pil;
typedef pair<ll,ll>pll;
const int mn=1e6+10;
const ll mod=1e9+7;
vector<int>v[3];
ll dp[76][76][76][3];
int sub(int a,int b,int c,int x){
    return min(lower_bound(v[0].begin(),v[0].end(),x)-v[0].begin(),(long)a)+
            min(lower_bound(v[1].begin(),v[1].end(),x)-v[1].begin(),(long)b)+
            min(lower_bound(v[2].begin(),v[2].end(),x)-v[2].begin(),(long)c);
}
int main(){
    int n;
    cin>>n;
    string s;
    cin>>s;
    for(int i=0;i<n;i++){
        if(s[i]=='V')v[0].push_back(i);
        else if(s[i]=='K')v[1].push_back(i);
        else v[2].push_back(i);
    }
    memset(dp,0x3f,sizeof(dp));
    dp[0][0][0][2]=0;
    for(int i=0;i<=v[0].size();i++){
        for(int j=0;j<=v[1].size();j++){
            for(int k=0;k<=v[2].size();k++){
                int a=(i!=v[0].size())?v[0][i]-sub(i,j,k,v[0][i]):0x3f3f3f3f,
                b=(j!=v[1].size())?v[1][j]-sub(i,j,k,v[1][j]):0x3f3f3f3f,
                c=(k!=v[2].size())?v[2][k]-sub(i,j,k,v[2][k]):0x3f3f3f3f;
                dp[i+1][j][k][0]=min(dp[i][j][k][0],min(dp[i][j][k][1],dp[i][j][k][2]))+a;
                dp[i][j+1][k][1]=min(dp[i][j][k][1],dp[i][j][k][2])+b;
                dp[i][j][k+1][2]=min(dp[i][j][k][0],min(dp[i][j][k][1],dp[i][j][k][2]))+c;
            }
        }
    }
    ll ans=0x3f3f3f3f3f3f3f3f;
    for(int i=0;i<3;i++)ans=min(ans,dp[v[0].size()][v[1].size()][v[2].size()][i]);
    printf("%lld",ans);
}


#include<stdio.h>
#include<set>
#include<vector>
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
set<string> st;
int tab[6][6]= {{1,5,4,6,2,3}  , {3,4,5,2,6,1} , {6,1,4,3,2,5} , {5,3,4,1,2,6} , {2,1,6,3,5,4},{4,1,5,3,6,2}};
int L;
vector<int> vec[24];
vector<char> s;
bool check()
    {
        vector<string> tmp;
        for(int i = 0 ; i< L;i++)
            {
                string is = "HHHHHH";
                for(int j = 0 ; j< 6;j++)
                    is[j] = s[vec[i][j] -1];
                //for(int j = 0 ; j < 6;j++)
                //    printf("%d ",vec[i][j]);
                //puts("");
               // cout << i << " : " << is  <<endl;
                if(st.count(is) > 0) return false;
                //st.insert(is);
                tmp.push_back(is);
            }
        for(int i = 0 ; i< tmp.size() ;i++)
            st.insert(tmp[i]);
        return true;
    }
int main()
    {
        for(int i = 0 ;i<6 ; i++)
            {
                for(int k = 1;k<5;k++)
                    {
                        vec[L].push_back(tab[i][0]);
                        for(int j = 0 ,p = k; j < 4 ;j++ ,p++)
                            vec[L] . push_back(tab[i][(p-1)%4+1]);
                        vec[L].push_back(tab[i][5]);
                        L++;
                    }

            }
        //for(int i = 0; i <L ;i++,puts(""))
cout << L;
        string ts;
        cin >> ts;
        int ans = 0;

        for(int i = 0 ; i <6;i++) s.push_back(ts[i]);sort（s.begin(),s.end());
        do
            {
                if(check()) ans++;
            }while(next_permutation(s.begin(),s.end()));
        cout << ans << endl;
        return 0;
    }


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string.h>
#include <string>
#include <vector>
#include <map>
#include <cmath>
#include <set>
#include <algorithm>
#include <queue>
#include <cassert>
#include <fstream>
#include <sstream>
#include <bitset>
#include <stack>
#include <list>
#include <hash_map>
#include <hash_set>
#include <ctime>
using namespace std;
#define debug1(x) cout << #x" = " << x << endl;
#define debug2(x, y) cout << #x" = " << x << " " << #y" = " << y << endl;
#define debug3(x, y, z) cout << #x" = " << x << " " << #y" = " << y << " " << #z" = " << z << endl;
#define debug4(x, y, z, w) cout << #x" = " << x << " " << #y" = " << y << " " << #z" = " << z << " " << #w" = " << w << endl;
template <class T>
ostream & operator << (ostream & out, const vector<T> & t)
{       out << t.size() << " {";        for (long long i = 0; i < t.size(); ++i)              out << t[i] << " ";     out << "}";     return out;}
template <class T>
ostream & operator << (ostream & out, const set<T> & t)
{       out << "{";     for (set<T>::iterator itr = t.begin(); itr != t.end(); ++itr)           out << *itr << " ";     out << "}";     return out;}

struct Cube
{
	string s;
	//        0        1       2     3        4     5
	//char front, back, up, down, left, right;

	Cube(string & is)
	{
		s = is;
	}

	void rotate(char & c1, char & c2, char & c3, char & c4)
	{
		char t = c1;
		c1 = c2;
		c2 = c3;
		c3 = c4;
		c4 = t;
	}

	void rotateX()	{ rotate(s[2], s[5], s[3], s[4]); }

	void rotateY()	{ rotate(s[0], s[5], s[1], s[4]);	}

	void rotateZ()	{ rotate(s[0], s[2], s[1], s[3]); }
};

set<string> app;
int ans;
string now;
string line;
bool used[10];
void search(int depth)
{
	if (depth == 6)
	{
		Cube nc(now);
		if (app.find(now) == app.end())
		{
			ans++;
			app.insert(now);
			for (int i = 0; i < 4; ++i)
			{
				nc.rotateX();
				for (int j = 0; j < 4; ++j)
				{
					nc.rotateY();
					for (int k = 0; k < 4; ++k)
					{
						nc.rotateZ();
						app.insert(nc.s);
					}
				}
			}
		}
		return;
	}

	for (int i = 0; i < line.length(); ++i)
		if (!used[i])
		{
			now[depth] = line[i];
			used[i] = true;
			search(depth + 1);
			used[i] = false;
		}
}

void init()
{
	memset(used, false, sizeof(used));
	cin >> line;
	ans = 0;

	now = string(6, ' ');
	search(0);

	cout << ans << endl;
}

void york()
{
}

int main()
{
	init();
	york();
	return 0;
}


#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=1e9+9;
int n,w,b;
int ans;
int fac[4005];
int c[4005][4005];
int C(int x,int y){
	if(c[x][y])return c[x][y];
	if(y==0)return 1;
	return c[x][y]=((x-1>y?C(x-1,y):0)+C(x-1,y-1))%mod;
}
signed main() {
	cin>>n>>w>>b;
	int mx=max(w,b);
	fac[0]=1;
	for(int i = 1;i <= mx;i ++) fac[i]=i*fac[i-1]%mod;
	for(int i = max(n-w,1);i<=b&&i<=n-2;++i)
		ans=(ans+C(b-1,i-1)*fac[b]%mod*fac[w]%mod*C(w-1,n-i-1)%mod*(n-i-1)%mod)%mod;
	cout<<ans;
	return 0;
}


#include<bits/stdc++.h>
#include<string.h>
#define ll long long
#define pf print
#define sf scanf
#define ff first
#define ss second
#define clr clear()
#define sz size()
#define pb push_back
#define mk make_pair
#define pi acos(-1)
#define inf 2000000
#define mod 1000000009
#define ull unsigned long long int
#define f(i,k,n) for(i=k;i<n;i++)
#define fr(i,n,k) for(i=n;i>=k;i--)
#define ent(a) scanf("%lld",&a)
#define ent2(a,b) scanf("%lld%lld",&a,&b)
#define ent3(a,b,c) scanf("%lld%lld%lld",&a,&b,&c)
#define mem(a) memset(a,0,sizeof(a))
#define vec(v,s) vector<ll>v[s]
#define arr(a,s) ll a[s];
/*#pragma GCC target ("avx2")
#pragma GCC optimization ("O3")
#pragma GCC optimization ("unroll-loops")
#pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")*/
//knight and king//
int dr[]= {2,2,-2,-2,1,-1,1,-1};
int dc[]= {1,-1,1,-1,2,2,-2,-2};
int dr1[]= {0,0,1,1,1,-1,-1,-1};
int dc1[]= {1,-1,1,0,-1,0,1,-1};
int dr2[]= {0,0,1,-1};
int dc2[]= {1,-1,0,0};
////////////////////////////
using namespace std;
#define ma 4005

ll dp[ma][ma];

ll cal(ll x,ll y)
{
    if(y<0)return 0;
    if(x==1)return 1;
    ll &r=dp[x][y];
    if(r!=-1)return r;
    r=cal(x,y-1);
    r+=cal(x-1,y-1);
    r%=mod;
    return r;
}

ll fac(ll n)
{
    ll m=1;
    for(ll i=1;i<=n;i++)
    {
        m*=i;
        m%=mod;
    }
    return m;
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    ll tc,i,j,n,w,b;
    while(cin>>n>>w>>b)
    {
        memset(dp,-1,sizeof(dp));
        ll ans=0;
        for(i=2;i<n;i++)
        {
            ll p=n-i;
            ll r=cal(i,w-1);
            ll r1=cal(n-i,b-1);-
            ll r2=(r*r1)%mod;
            r2=r2*(i-1);
            r2%=mod;
            ans+=r2;
            ans%=mod;
        }
        ll p=ans*fac(w);
        p%=mod;
        p=p*fac(b);
        p%=mod;
        cout<<p<<endl;

    }
    return 0;
}


#include <cstdio>
const int MOD = (int)(1e9) + 9;
const int N = 4000 + 9;
int f[N][N],n,c[N * 2][N],res;
int fac(int x)
{
    long long res = 1;
    for (int i = 1; i <= x; ++i)
        res = res * i % MOD;
    return res;
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("306C.in","r",stdin);
    freopen("306C.out","w",stdout);
    #endif
    int a[2];
    scanf("%d%d%d", &n, &a[1], &a[0]);
    for (int i = 1; i <= a[1]; ++i)
        f[1][i] = 1;
    f[0][0] = 1;
    for (int i = 2; i <= n; ++i) {
        int sum = f[i - 2][0];
        for (int j = 1; j <= a[i & 1]; ++j) {
            f[i][j] = (f[i][j] + sum) % MOD;
            sum = (sum + f[i - 2][j]) % MOD;
        }
    }
    c[0][1] = 1;
    for (int i = 1; i <= a[0] + a[1]; ++i)
        for (int j = 1; j <= n && j <= i; ++j)
            c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % MOD;
    for (int i = 2; i < 3; ++i)
        res = (res + 1ll * f[i][a[i & 1]] * f[i + 1][a[i + 1 & 1]] % MOD * c[a[0] + a[1] - i][n - i] % MOD) % MOD;
    printf("%I64d\n", 1ll * res * fac(a[0]) % MOD * fac(a[1]) % MOD);
    //printf("%d\n", 1ll * f[n][a[n & 1]] * f[n - 1][a[n - 1 & 1]] % MOD * fac(a[0]) % MOD * fac(a[1]) % MOD);
}
#include <cstdio>
const int MOD = (int)(1e9) + 9;
const int N = 4000 + 9;
int f[N][N],n,c[N * 2][N],res;
int fac(int x)
{
    long long res = 1;
    for (int i = 1; i <= x; ++i)
        res = res * i % MOD;
    return res;
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("306C.in","r",stdin);
    freopen("306C.out","w",stdout);
    #endif
    int a[2];
    scanf("%d%d%d", &n, &a[1], &a[0]);
    for (int i = 1; i <= a[1]; ++i)
        f[1][i] = 1;
    f[0][0] = 1;
    for (int i = 2; i <= n; ++i) {
        int sum = f[i - 2][0];
        for (int j = 1; j <= a[i & 1]; ++j) {
            f[i][j] = (f[i][j] + sum) % MOD;
            sum = (sum + f[i - 2][j]) % MOD;
        }
    }
    c[0][1] = 1;
    for (int i = 1; i <= a[0] + a[1]; ++i)
        for (int j = 1; j <= n; ++j)
            c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % MOD;
    for (int i = 2; i < 3; ++i)
        res = (res + 1ll * f[i][a[i & 1]] * f[i + 1][a[i + 1 & 1]] % MOD * c[a[0] + a[1] - i][n - i] % MOD) % MOD;
    printf("%I64d\n", 1ll * res * fac(a[0]) % MOD * fac(a[1]) % MOD);
    //printf("%d\n", 1ll * f[n][a[n & 1]] * f[n - 1][a[n - 1 & 1]] % MOD * fac(a[0]) % MOD * fac(a[1]) % MOD);
}


#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
using namespace std;
const double pie=acos(-1.0);
double d=20.0*sin(pie*0.3);
struct point
{
    double x,y;
    point(double _x=0,double _y=0){x=_x;y=_y;}
}p[10];
int main()
{
    int n;
    scanf("%d",&n);
    double t=d/2.0-5.0;
    p[0]=point(0,0);
    p[1]=point(d-t,-sqrt(100-t*t));
    p[2]=point(d/2.0,10*cos(pie*0.3));
    p[3]=point(t,-sqrt(100-t*t));
    int sum=4*n+1;
    printf("%d\n",sum);
    for(int i=0;i<sum;i++)
    {
        printf("%.12f %.12f\n",p[i%4].x,p[i%4].y);
        p[i%4]+=d;
    }
    for(int i=0;i<n;i++) printf("%d %d %d %d %d\n",1+4*i,3+4*i,5+4*i,2+4*i,4+4*i);
    for(int i=0;i<n;i++) printf("%d %d %d %d ",1+4*i,2+4*i,3+4*i,4+4*i);
    for(int i=n;i>0;i--) printf("%d ",4*i+1);
    printf("1\n");
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define forn(i, x, n) for(int i = int(x); i <= int(n); ++i)
#define for1(i, n, x) for(int i = int(n); i >= int(x); --i)
#define file ""
#define pb push_back
#define x first
#define y second
#define _bits __builtin_popcountll

typedef long long ll;
typedef long double ld;
typedef pair <ld, ld> PII;

const int N = 2e6 + 1;
const int INF = 1e9 + 9;
const int B = 1e9 + 7;
const ld pi = acos(-1);
const ld gratio = (1 + sqrt(5)) / 2.0;

PII operator - (const PII &a, const PII &b) {
	return PII(a.x - b.x, a.y - b.y);
}

PII operator + (const PII &a, const PII &b) {
	return PII(a.x + b.x, a.y + b.y);
}

PII operator * (const PII &a, const ld &b) {
	return PII(a.x * b, a.y * b);
}

PII operator - (const PII &a) {
	return PII(-a.x, -a.y);
}

ostream & operator << (ostream &out, const PII &p) {
	out << "(" << p.x << ", " << p.y << ")";
	return out;
}

PII turn (const PII &a, const ld &angle) {
	return PII (
		a.x * cos(angle) - a.y * sin(angle),
		a.x * sin(angle) + a.y * cos(angle)
	);
}

const PII height(0, -100);
const PII d1 = -turn(height, 2 * pi - 0.1 * pi);
const PII d2 = turn(height, 0.1 * pi);
const PII side1 = turn(d1 * (1 / gratio), 0.2 * pi);
const PII side2 = PII(-side1.x, side1.y);

int m = 5;
PII p[N] = {
	PII(0, 0),
/*	PII(3.830127018922193, 3.366025403784439), */ PII(-3.601321235851749, 10.057331467373021),
/*	PII(-3.601321235851749 10.057331467373021),*/ PII(10.411264148588986, 18.147501411122495),
/*	PII(0.466045194906253 19.192786043799030), */ PII(0.466045194906253, 19.192786043799030),
/*	PII(10.411264148588986 18.147501411122495),*/ PII(3.830127018922193, 3.366025403784439),
/*	PII(12.490381056766580 8.366025403784439)  */ PII(12.490381056766580, 8.366025403784439)
};

int main() {
#ifdef machine42
	freopen(file"in", "r", stdin);
	freopen(file"out", "w", stdout);
#endif
	ios_base :: sync_with_stdio (0);
	cin.tie(0);
	cerr << fixed << setprecision(10);
	cout << fixed << setprecision(10);

	int n;
    cin >> n;
    PII side = p[5] - p[1];
    forn(i, 2, n) {
    	forn(j, 2, 5) {
			++m;
			p[m] = p[m - 4] + side;
		}
    }
    cout << m << "\n";
    forn(i, 1, m)
    	cout << double(p[i].x) << " " << double(p[i].y) << "\n";
    forn(i, 1, n) {
    	cout << 4 * (i - 1) + 1 << " ";
    	cout << 4 * (i - 1) + 3 << " ";
    	cout << 4 * (i - 1) + 5 << " ";
    	cout << 4 * (i - 1) + 2 << " ";
    	cout << 4 * (i - 1) + 4 << " ";
    	cout << "\n";
    }
    forn(i, 1, 4 * n + 1)
    	cout << i << " ";
    for1(i, n, 1)
    	cout << 4 * (i - 1) + 1 << " ";
    cout << "\n";

	return 0;
}


#include<limits>
#include<iostream>
#include<queue>
#include<climits>
#include<cstring>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<cmath>
#include<cstdlib>
using namespace std;

struct Point
{
    double x,y;
    Point(double a=0,double b=0)
    {
        x=a;y=b;
    }
};

int main()
{
    int N;
    cin >> N;
    Point A;
    vector<Point> V;
    for(int i = 0; i < N; ++i)
    {
        V.push_back(A);
        A.x += 20*cos(72*M_PI/180.0) + 10;
    }
    A = V.back();
    for(int i = 0; i < N; ++i)
    {
        A.x -= 10*cos(72*M_PI/180.0) + 10;
        A.y -= 10*cos(18*M_PI/180.0);
        V.push_back(A);
        A.x += 5;
        A.y += 10*cos(18*M_PI/180.0) + 10*cos(72*M_PI/180.0);
        V.push_back(A);
        A.x += 5;
        A.y -= 10*cos(18*M_PI/180.0) + 10*cos(72*M_PI/180.0);
        V.push_back(A);
        A.x -= 10*cos(72*M_PI/180.0) + 10;
        A.y += 10*cos(18*M_PI/180.0);
        V.push_back(A);
    }
    for(int i = 0; i < V.size(); ++i)
        printf("%0.10lf %0.10lf\n",V[i].x,V[i].y);
}
/*
2
0 1 0 0 0 0 0 0 0 0

1
0 1 0 0 0 0 0 0 0 0

 */


#include<bits/stdc++.h>

#define int long long

using namespace std;

int n,x,y,id;

int dx[6]={-1,-2,-1,1,2,1};
int dy[6]={2,0,-2,-2,0,2};

void Work(){
	for(int i=0;i<6;i++){
		int t=min(n,id+1);
		x+=dx[i]*t;
		y+=dy[i]*t;
		n-=t;
	}
	printf("%d %d\n",x,y);
}

void Init(){
	cin>>n;
	if(!n){
		puts("0 0");
		exit(0);
	}
	for(id=sqrt(n/3.0);id*(id+1)*3>=n;id--);
	n-=id*(id+1)*3;
	x=id*2+2;
}

int main(){
	Init();
	Work();
	return 0;
}


#pragma comment(linker, "/STACK:36777216")
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <set>
#include <map>

#define M_PI 3.14159265358979323846

using namespace std;

typedef unsigned __int64 ui;
typedef long long ll;

pair <ll, ll> pos;

ll sd, n,s;

void out()
{
	if (sd == s) {
	cout << pos.first << ' ' << pos.second << endl;
	exit(0);
}
}

int main()
{
	cin.sync_with_stdio(false);
	cin >> s;
	n = (3 + (int)sqrt(9 + 12 * s)) / 6; // ring number
	//cout << n << endl;
	sd = 3 * (n*n - n);//sdelano shagov
	pos = { 2 * (n-1), 0 };
	out();
	++sd;
	pos = { pos.first + 1, pos.second + 2 };
	out();

	if (s - sd > n - 1)//levo-verh
	{
		sd += n - 1;
		pos = { pos.first - 1 * (n-1), pos.second + 2 *(n-1)};
	}
	else
	{
		for (int i = 0; i < n - 1; ++i)
		{
			++sd;
			pos = { pos.first - 1, pos.second + 2 };
			out();
		}
	}
	out();

	if (s - sd > n)//levo
	{
		sd += n;
		pos = { pos.first - 2 * n, pos.second};
	}
	else
	{
		for (int i = 0; i < n; ++i)
		{
			++sd;
			pos = { pos.first - 2, pos.second};
			out();
		}
	}
	out();

	if (s - sd > n)//levo-niz
	{
		sd += n;
		pos = { pos.first - 1 * n, pos.second - 2*n};
	}
	else
	{
		for (int i = 0; i < n; ++i)
		{
			++sd;
			pos = { pos.first - 1, pos.second - 2 };
			out();
		}
	}
	out();

	if (s - sd > n)//pravo-niz
	{
		sd += n;
		pos = { pos.first + 1 * n, pos.second - 2 * n };
	}
	else
	{
		for (int i = 0; i < n; ++i)
		{
			++sd;
			pos = { pos.first + 1, pos.second - 2 };
			out();
		}
	}
	out();

	if (s - sd > n)//pravo
	{
		sd += n;
		pos = { pos.first + 2 * n, pos.second};
	}
	else
	{
		for (int i = 0; i < n; ++i)
		{
			++sd;
			pos = { pos.first + 2, pos.second};
			out();
		}
	}
	out();

	if (s - sd > n - 1)//pravo-verh
	{
		sd += n;
		pos = { pos.first + 1 * (n - 1), pos.second + 2 * (n-1) };
	}
	else
	{
		for (int i = 0; i < n; ++i)
		{
			++sd;
			pos = { pos.first + 1, pos.second + 2 };
			out();
		}
	}
	out();

	return 0;
}


    #pragma GCC optimize("Ofast")
    #include <iostream>
    #include <map>
    #include <vector>
    #include <deque>
    #include <algorithm>
    #include <bitset>
    #include <cstring>
    #include <math.h>
    #include <string>
    #include <set>
    #include <iomanip>
    #include <bitset>
    #include <random>
    #include <complex>
    #include <random>
    #include <cassert>
    #include <unordered_map>
    #include <unordered_set>
    using namespace std;
    #define pb push_back
    #define ll long long
    #define mp make_pair
    #define fdeg firdeg
    #define snd second
    #define ins insert
    #define ld long dorle
    #define mt make_tuple
    #define fst first
    const dorle PI = acos(-1);
    // = 5e5 + 17;
    ll MOD = 1e9 + 7;
    const int INF = 1e9;
    const int MaXN = 150;
    const int N = 2e5 + 1000;
    const int LOG = 64;
    const int FACT = 120;
    ld ecr = 1e-8;
    random_device rd;
    mt19937 rnd(rd());
    uniform_int_distribution<ll> nextRand(0,(ll)1e9);
    template<class A, class B>
    void sum(A &a, B b)
    {
        a += b;
        if (a < 0LL) a += MOD;
        if (a >= MOD) a -= MOD;
    }
    ll add(ll a, ll b)
    {
        a += b;
        if (a < 0) a += MOD;
        if (a >= MOD) a -= MOD;
        return a;

    }
    int to_i(char c)
    {
        return c - 'a';
    }
    ll mult(ll a, ll b) {
        ll val = a * b - (ll) ((ld) a * b / MOD) * MOD;
        if (val < 0) {
            val += MOD;
        }
        if (val >= MOD) {
            val -= MOD;
        }
        return val;
    }
    ll gcd (ll a, ll b)
    {
        if (b == 0)
            return a;
        else
            return gcd (b, a % b);
    }
    ll gcd_eu (ll a, ll b, ll & x, ll & y)
    {
        if (a == 0)
        {
            x = 0LL; y = 1LL;
            return b;
        }
        ll x1, y1;
        ll d = gcd_eu (b%a, a, x1, y1);
        x = y1 - (b / a) * x1;
        y = x1;
        return d;
    }
    long long poww(long long a, long long b)
    {
        long long val = 1;
        a %= MOD;
        while (b > 0)
        {
            if (b % 2) val = mult(a, val);
            a = mult(a, a);
            b >>= 1;
        }
        return val % MOD;
    }
    ll inv(ll a)
    {
        return poww(a , MOD - 2);
    }
    int logP(int a, int p)
    {
        int logg = 0;
        while (a % p == 0)
        {
            a /= p;
            logg++;
        }
        return logg;
    }

    int calc(vector<int>& a, vector<int>& b, int p) {
        int n = a.size(), m = b.size();
        vector<int> logA(n), logB(m);
        for (int i = 0; i < n; i++)
            logA[i] = logP(a[i], p);
        for (int i = 0; i < m; i++)
            logB[i] = logP(b[i], p);
        ll mna = 1e18, mnb = 1e18;
        for(int i = 0; i < n; i++)
            mna = min(mna, (ll)logA[i]);
        for(int i = 0; i < m; i++)
            mnb = min(mnb, (ll)logB[i]);
        ll mnx = max(mna, mnb);
        int aa = 0, bb = 0;
        for (int i = 0; i < n; i++)
            if (logA[i] < mnx + 1)
                aa++;
        for (int i = 0; i < m; i++)
            if (logB[i] < mnx + 1)
                bb++;
        return add(poww(mnx + 1, aa),poww(mnx + 1, bb) - 1);
    }
    vector<int> pr;
    void add_to_pr(ll x)
    {
        for (int i = 2; i * i <= x; i++)
        {
            //cout << x << " ";
            if (x % i == 0)
            {
                while (x % i == 0) x /= i;
                pr.pb(i);
            }
        }
        if (x > 1)
        {
            pr.pb(x);
        }
    }

const int dx[6] = {-1, -2, -1, 1, 2, 1};
const int dy[6] = {2, 0, -2, -2, 0, 2};
int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    ll n, l = -1, r = 1e9;
    cin >> n;
    while (r - l > 1)
    {
        ll mid = (l + r) / 2;
        ll x = mid * (mid + 1) * 3;
        if (x >= n)
            r = mid;
        else l = mid;
    }
    ll x = 2 * r, y = 0;
    n -= l * (l + 1) * 3;
    for(int i = 0; i < 6; i++)
    {
        ll z = min(r, n);
        x += dx[i] * z;
        y += dy[i] * z;
        n -= z;
    }
    cout << x << " " << y << "\n";
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define ll long long int
#define inf 1000000000000
#define mod 1000000007
#define pb push_back
#define mp make_pair
#define all(v) v.begin(),v.end()
#define S second
#define F first
#define boost1 ios::sync_with_stdio(false);
#define boost2 cin.tie(0);
#define mem(a,val) memset(a,val,sizeof a)
#define endl "\n"
#define maxn 305

ll arr[maxn],brr[maxn],ncr[maxn][maxn],sum[maxn],dp[maxn][maxn];
map<ll,ll>store;

inline ll add(ll x,ll y)
{
	x+=y;
	if(x>=mod)
	x-=mod;
	return x;
}
inline ll mul(ll x,ll y)
{
	return (x*y)%mod;
}
int main()
{
	boost1;boost2;
	ll i,j,n,x,y,ans=0,cnt,temp,k,l,ctr=0;

	for(i=0;i<maxn;i++)
	{
		ncr[i][0] = 1;
		for(j=1;j<=i;j++)
		ncr[i][j] = add(ncr[i-1][j-1],ncr[i-1][j]);
	}
	cin>>n;
	for(i=1;i<=n;i++)
	cin>>arr[i];
	for(i=1;i<=n;i++)
	{
		x=arr[i];
		temp=1;
		for(j=2;j*j<=x;j++)
		{
			if(arr[i]%j)
			continue;
			cnt=0;
			while(arr[i]%j==0)
			{
				arr[i]=arr[i]/j;
				cnt++;
			}
			if(cnt&1)
			temp=temp*j;
		}
		if(arr[i]!=1)
		temp=temp*arr[i];
		store[temp]++;
	}
	for(auto it:store)
	{
		ctr++;
		brr[ctr]=it.S;
	}
	/*cout<<endl;
	for(i=1;i<=ctr;i++)
	cout<<brr[i]<<" ";
	cout<<endl;*/
	for(i=1;i<=ctr;i++)
	sum[i]=sum[i-1]+brr[i];
	/*cout<<endl;
	for(i=1;i<=ctr;i++)
	cout<<sum[i]<<" ";
	cout<<endl;*/
	dp[1][brr[1]-1]=1;
	for(i=1;i<ctr;i++)
	{
		for(j=0;j<=n;j++)
		{
			if(dp[i][j]==0)
			continue;
			for(k=1;k<=min(sum[i]+1,brr[i+1]);k++)
			{
				for(l=0;l<=min(j,k);l++)
				dp[i+1][j-l+brr[i+1]-k]=add(dp[i+1][j-l+brr[i+1]-k],mul(dp[i][j],mul(ncr[j][l],mul(ncr[sum[i]+1-j][k-l],ncr[brr[i+1]-1][k-1]))));
			}
		}
	}
	ans=dp[ctr][0];
	//cout<<ans<<endl;
	for(i=1;i<=ctr;i++)
	{
		for(j=1;j<=brr[i];j++)
		ans=mul(ans,j);
	}
	cout<<ans;
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int N=773;
const long long mod=23513892331591;
int n,ap[400],Fact[2*N];;
long long a[N],val[N];
int code(int x)
{
    int ans=1;
    for(int i=2;i*i<=x;++i)
    {
        int par=0;
        while(x%i==0) par^=1,x/=i;
        if(par&1) ans*=i;
    }
    if(x>1) ans*=x;
    return ans;
}
const int dpmod=1e9+7;
int dp[N][N],Com[2*N][2*N];
int mul(int aq, int b)
{
	return (long long)aq*b%dpmod;
}
void combii()
{
	Com[0][0]=1;
	for(int i=1;i<2*N;++i)
	{
		Com[i][0]=1;
		Com[i][1]=i;
		Com[i][i]=1;
		for(int j=2;j<i;++j) Com[i][j]=(Com[i-1][j]+Com[i-1][j-1])%dpmod;
	}
}
void Solve()
{
	Fact[0]=1;
	combii();
	for(int i=1;i<2*N;++i) Fact[i]=mul(i,Fact[i-1]);
	int on=n;
	n=0;
	dp[1][ap[1]-1]=1;
	for(int i=1;i<=on;++i)
	{
		n+=ap[i];
		for(int j=0;j<n;++j)
		{
			dp[i][j]%=dpmod;
			for(int k=1;k<=ap[i+1];++k)
			{

				for(int l=0;l<=k;++l)
				{
					int nr=j-l+ap[i+1]-k;
					if(nr<0) continue;
					long long delta=mul(Com[j][l],Com[n-j+1][k-l]);
					delta=mul(delta,Com[ap[i+1]-1][k-1]);
					dp[i+1][nr]=add(dp[i+1][nr],mul(delta,dp[i][j]));
				}
			}
		}
	}
	int valq=dp[on][0];
	for(int i=1;i<=on;++i) valq=1LL*valq*Fact[ap[i]]%dpmod;
	cout<<valq;
}
int main()
{
    cin>>n;
	for(int i=1;i<=n;++i) cin>>a[i];
	for(int i=1;i<=n;++i) val[i]=code(a[i]);
	sort(val+1,val+n+1);
	map <long long,int> aux;
	for(int i=1;i<=n;++i) ++aux[val[i]];
	vector <int> vec;
	int new_n=0;
	for(auto it:aux) ap[++new_n]=it.second;
	n=new_n;
	Solve();
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define ln '\n'
#define rep(i,n) for(int i=0;i<(n);++i)
#define drep(i,n) int i = 0;for(;i<(n);++i)
#define FOR(i,s,e) for(int i=s;i<=(e);++i)
#define FORR(i,s,e) for(int i=s;i>=(e);--i)
#define fore(a, x) for(auto& a : x)
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
#define ft first
#define sd second
#define pb push_back
#define eb emplace_back
#define all(a) a.begin(),a.end()
#define Fill(a,b) memset(a,b,sizeof(a))
template<typename T1, typename T2> bool Max(T1& a, T2 b) {return a<b?a=b,1:0;}
template<typename T1, typename T2> bool Min(T1& a, T2 b) {return a>b?a=b,1:0;}

template<int MOD>
struct ModInt {
  unsigned x;
  ModInt() : x(0) { }
  ModInt(signed sig) : x(sig) {  }
  ModInt(signed long long sig) : x(sig%MOD)  { }
  int get() const { return (int)x; }
  ModInt pow(unsigned p) { ModInt res = 1, a = *this; while (p) { if (p & 1) res *= a; a *= a; p >>= 1; } return res; }

  ModInt &operator+=(ModInt that) { if ((x += that.x) >= MOD) x -= MOD; return *this; }
  ModInt &operator-=(ModInt that) { if ((x += MOD - that.x) >= MOD) x -= MOD; return *this; }
  ModInt &operator*=(ModInt that) { x = (unsigned long long)x * that.x % MOD; return *this; }
  ModInt &operator/=(ModInt that) { return (*this) *= that.power(MOD - 2); }

  ModInt operator+(ModInt that) const { return ModInt(*this) += that; }
  ModInt operator-(ModInt that) const { return ModInt(*this) -= that; }
  ModInt operator*(ModInt that) const { return ModInt(*this) *= that; }
  ModInt operator/(ModInt that) const { return ModInt(*this) /= that; }
};
typedef ModInt<1000000007> mint;

const int N = 200001;
mint f[2][300];
mint C[301][301];
mint P[301];

bool isper(ll i){
  ll t = sqrt(i);
  return t*t == i;
}

void solve() {
  int n;
  ll v;
  cin>>n;
  C[0][0] = 1;
  P[0] = 1;
  FOR(i,1,n){
    C[i][0] = 1;
    P[i] = P[i-1]*i;
    FOR(j,1,i)C[i][j] = C[i-1][j] + C[i-1][j-1];
  }
  vector<pll> grp;
  rep(i,n){
    cin>>v;
    bool found = 0;
    fore(e,grp){
      if(isper(e.ft*v)){
        e.sd++;
        found = 1;
        break;
      }
    }
    if(!found) grp.eb(v,1);
  }
  int c = 0;
  int sz = 0;
  f[0][0] = 1;
  fore(e,grp){
    c ^= 1;
    int cur = e.sd;
    rep(i,sz+cur)f[c][i]=0;
    FOR(sg,1,min(cur, sz+1)) FOR(bad,0,max(0,sz-1)) FOR(badsg,0,min(bad,sg)){
        f[c][cur-sg+bad-badsg] += f[!c][bad] * P[cur] * C[cur-1][sg-1] * C[bad][badsg] * C[sz+1-bad][sg-badsg];
      }
    }
    sz += cur;
  }
  cout<<f[c][0].x<<ln;

}

void init(){
}

int main(void) {
  ios::sync_with_stdio(false); cin.tie(0); cout.setf(ios::fixed); cout.precision(20);

  init();
  int TC = 1;
#if 0
  cin>>TC;
#endif
  FOR(TI,1,TC) {
    //cout << "Case #" << TI << ": ";
    solve();
  }

  return 0;
}


#include <iostream>
#include <iomanip>
#include <bits/stdc++.h>

#define forn(i, n) for (int i = 0; i < int(n); i++)
#define ford(i, n) for (int i = int(n) - 1; i >= 0; i--)
#define fore(i, l, r) for (int i = int(l); i < int(r); i++)
#define correct(x, y, n, m) (0 <= (x) && (x) < (n) && 0 <= (y) && (y) < (m))
#define all(a) (a).begin(), (a).end()
#define sz(a) int((a).size())
#define pb(a) push_back(a)
#define mp(x, y) make_pair((x), (y))
#define x first
#define y second

using namespace std;

typedef long long li;
typedef long double ld;
typedef pair<int, int> pt;

template<typename X> inline X abs(const X& a) { return a < 0? -a: a; }
template<typename X> inline X sqr(const X& a) { return a * a; }

const int INF = int(1e9);
const li INF64 = li(1e18);
const ld EPS = 1e-9, PI = 3.1415926535897932384626433832795;

int a, b;

inline bool read() {
	return !!(cin >> a >> b);
}

int c[] = { 6, 2, 5, 5, 4, 5, 6, 3, 7, 6 };

inline void solve() {
	int ans = 0;
	fore(i, a, b + 1) {
		int x = i;
		while (x) {
			ans += c[x % 10];
			x /= 10;
		}
	}
	cout << ans << endl;
}

int main() {
#ifdef SU1
    assert(freopen("input.txt", "rt", stdin));
    //assert(freopen("output.txt", "wt", stdout));
#endif

    cout << setprecision(10) << fixed;
    cerr << setprecision(5) << fixed;

    while (read()) {
		solve();
		//break;
	}

    return 0;
}


#include <iostream>
#include <vector>
#include <string>

using namespace std;

int getSegmentCountOfAString(vector<int>&vec,string &integer){
	int sum = 0;
	for(int i = 0;i<integer.size();i++){
		sum += vec[integer[i]-'0'];
	}
	return sum;
}

// int getSegmentCountOfAInteger(vector<int>vec,)

int main(){
	int a,b;
	cin>>a>>b;
	long long int sum = 0;
	vector<int>segmentCountOfIntegers{6,2,5,5,4,5,6,3,7,6};
	for(int i = a;i<=b;i++){
		sum += getSegmentCount(segmentCountOfIntegers,to_string(i));
	}
	cout<<sum<<endl;
}


// stdafx.cpp : source file that includes just the standard includes
// cf620B.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information

#include "stdafx.h"

// TODO: reference any additional headers you need in STDAFX.H
// and not in this file


#include <iostream>

using namespace std;

int countSegmentsOfADigit(int digit)
{
	switch (digit)
	{
	case 0:
		return 6;
	case 1:
		return 2;
	case 2:
		return 5;
	case 3:
		return 5;
	case 4:
		return 4;
	case 5:
		return 5;
	case 6:
		return 6;
	case 7:
		return 3;
	case 8:
		return 7;
	case 9:
		return 6;
	default:
		break;
	}
}

int countDigits(int n)
{
	int result = 0;
	while (n > 0)
	{
		result += 1;
		n /= 10;
	}
	return result;
}

int countSegments(int n)
{
	if (n == 0)
		return 0;
	int count = countDigits(n);
	int k = pow(10, count);
	int result = 0;
	int previousDigit = 0, currentDigit;
	for (int i = 0; i < n; i++)
	{
		k /= 10;
		currentDigit = n / k;
		n = n%k;
		for (int j = 0; j <= 9; j++)
		{
			if (j == 0 || j>currentDigit)
				result += countSegmentsOfADigit(j)*previousDigit*k;
			else if (j == currentDigit)
				result += countSegmentsOfADigit(j)*previousDigit + countSegmentsOfADigit(j)*(n + 1);
			else
				result += countSegmentsOfADigit(j)*(previousDigit + 1);
		}
		previousDigit = currentDigit;
	}
	return result;
}

void main()
{
	int a, b;
	cin >> a >> b;
	int printedSegments = countSegments(b) - countSegments(a - 1);

	cout << printedSegments;

	cin.get();
	cin.get();
}


#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>

using namespace std;

int rr[100001][2];
bool acc[100001], not[100001];
set<int> s1;
int tot,n,m;
char s[10];

int main(){
    int last=-1,tt;
    scanf("%d %d", &n, &m);
    for(int i=1;i<=m;i++){
        scanf("%s %d", s, &rr[i][1]), rr[i][0]=(s[0]=='-')?-1:1;
        if (!not[rr[i][1]]) not[rr[i][1]]=1, tot++;
        if(!acc[rr[i][1]]&&rr[i][0]==-1) last=rr[i][1];
        else acc[rr[i][1]]+=rr[i][0];
    }
    if(last!=-1) rr[0][0]=1, rr[0][1]=rr[last][1];
    memset(acc, 0, sizeof(acc));
    if(last==-1) tt=1;
    else tt=0;
    int check=1;
    for(int i=tt;i<=m;i++){
        if(rr[i][0]==1) s1.insert(rr[i][1]);
        else if(s1.find(rr[i][1])!=s1.end()) s1.erase(rr[i][1]);
        if(s1.find(rr[tt][1])==s1.end()&&s1.size()!=0){
            check=0;
            break;
        }
    }
    if(check) not[rr[tt][1]]=0, tot--;

    printf("%d\n", n-tot);
    for(int i=1;i<=n;i++)
        if(!not[i])
            printf("%d ", i);
    //system("pause");
    return 0;
}


#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#include <set>

using namespace std;

int log_op[111111];
int log_man[111111];

int init_state[111111]; // 0 unk 1 in 2 out
bool meet[111111];

bool bye[111111];

int main(void)
{
	int n = 0;
	int m = 0;
	scanf("%d %d",&n,&m);
	for(int i = 0;i < m;i++)
	{
		char op[16] = {0};
		int man = 0;
		scanf("%s %d",op,&man);
		log_op[i] = op[0];
		log_man[i] = man;

		if(!meet[man])
		{
			if(log_op[i] == '+') init_state[man] = 2;
			else init_state[man] = 1;
			meet[man] = true;
		}
	}

	set<int> here;
	set<int> not;
	set<int> banned;
	for(int i = 1;i <= n;i++)
	{
		if(init_state[i] == 1) here.insert(i);
		else if(init_state[i] == 2) not.insert(i);
	}
	if(here.size() != 0)
	{
		for(auto x: not)
		{
			banned.insert(x);
		}
		not.clear();
	}
	int max_online = here.size();
	for(int i = 0;i < m;i++)
	{
		if(log_op[i] == '+')
		{
			if(!here.size() && i && log_op[i-1] == '-' && log_man[i-1] == log_man[i])
			{
				here.insert(log_man[i]);
				not.erase(log_man[i]);
				continue;
			}
			if(here.size() || max_online) banned.insert(log_man[i]);
			if(not.size())
			{
				for(auto& x: not) if(x != log_man[i]) banned.insert(x);
				not.clear();
			}
			here.insert(log_man[i]);
			max_online = max<int>(max_online, here.size());
		}
		else if(log_op[i] == '-')
		{
			here.erase(log_man[i]);
			if(here.size()) banned.insert(log_man[i]);
			else if(!banned.count(log_man[i]))
			{
				not.insert(log_man[i]);
			}
		}
	}
	vector<int> candidate;
	for(int i = 1;i <= n;i++) if(!banned.count(i)) candidate.push_back(i);
	printf("%d\n",candidate.size());
	for(auto& x: candidate) printf("%d ",x);
	puts("");
	while(getchar() != EOF);
	return 0;
}


#include <bits/stdc++.h>
#define MOD 1000000007
using namespace std;
typedef long long ll;

int n, m;

int st[100001];
bool l[100001];

pair<char, int> q[100001];

vector<int> nr;

int main()
{
	cin >> n >> m;
	int cnt = 0;
	for (int i = 1; i <= n; ++i) {
		st[i] = 2;
		l[i] = true;
	}
	for (int i = 0; i < m; ++i) {
		char c;
		int d;
		scanf(" %c %d", &c, &d);

		q[i] = {c, d};
		if (st[d] == 2) {
			if (c == '+') {
				st[d] = 0;
				nr.push_back(d);
			} else {
				st[d] = 1;
				++cnt;
			}
		}
	}
	//cout << cnt << endl;
	if (cnt != 0) {
		for (int i = 0; i < nr.size(); ++i) {
			l[nr[j]] = false;
		}
		nr.clear();
	}
	for (int i = 0; i < m; ++i) {
		char c = q[i].first;
		int d = q[i].second;
		if (c == '+') {
			for (int j = 0; j < nr.size(); ++j) {
				if (nr[j] != d) {
					l[nr[j]] = false;
				}
			}
			nr.clear();
			if (cnt != 0) {
				l[d] = false;
			}
			++cnt;
		} else {
			--cnt;
			if (cnt != 0) {
				l[d] = false;
			} else if (l[d]) {
				nr.push_back(d);
			}
		}
	}
	vector<int> sol;
	for (int i = 1; i <= n; ++i) {
		if (l[i]) {
			sol.push_back(i);
		}
	}
	cout << sol.size() << endl;
	for (int i = 0; i < sol.size(); ++i) {
		printf("%d ", sol[i]);
	}
	cout << endl;
	return 0;
}


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

int main()
{
    int h,w;
    int c[h][w];
    for(int i=0;i<h;i++)
    {
        for(int j=0;j<w;j++)
        {
            cin>>c[i][j];
        }
    }
    int i=0, ctr=0;
        for(int j=0;j<w;j++)
        {
            if(c[i][j]=='*')
            {
               ctr++;
            }
            if(j==w-1)
            {
                while(i!=h-1)
                {
                    if(ctr[i][j]=='*')
                    {
                        ctr++;
                    }
                         i++;
                }
            }
        }
        cout<<ctr;
        return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define fast ios_base ::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define   fi(a,b) for(int i=a;i<b;i++)
#define   fj(a,b) for(int j=a;j<b;j++)
#define   ff first
#define   ss second
#define   ll long long
#define   ld long double
#define   ull unsigned long long
#define   bp(x) __builtin_popcount(x)
#define   pr(x) for(auto it: x) cout<<it<<" "; cout<<endl;
#define   getMax(x) max_element(x.begin(),x.end())
#define   getMin(x) min_element(x.begin(),x.end())
#define   end "\n"
typedef   vector<int> vi;
typedef   vector< pair<int,int> > vii;
typedef   vector<long long> vl;
typedef   pair<int,int> pii;
typedef   pair<ll,ll> pll;
typedef   vector< pair<ll,ll> > vll;
//int dx[]={1,0,-1,0};
//int dy[]={0,1,0,-1};
//int dx[]={-1,0,1,1,1,0,-1,-1};
//int dy[]={-1,-1,-1,0,1,1,1,0};
map<int,int>mp;
ll gcd(ll a, ll b) {
    if(a<b) swap(a, b);
    if (b == 0)
        return a;
    return gcd(b, a % b);
}

ll lcm(ll a, ll b){
    return (a*b)/gcd(a, b);
}

 void solve()
{
   int r,c;
   cin>>r>>c;
   string cake[r];
   for(int i=0;i<r;i++)
   {
       cin>>cake[i];
   }
   int ctr=0;
   for(int i=0;i<r;)
   {
           if(cake[i][j]=='*')
           ctr++;
           if(i==r-1 and j==c-1)
           {
               break;
           }
           else
           if(i==r-1)
           j++;
           else
           if(j==c-1)
           i++;
           else
           if(cake[i+1][j]=='*')i++;
           else if(cake[i][j+1]=='*') j++;

   }
   cout<<ctr;
}

int main(){
    #ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    #endif
    fast;
    solve();
    return 0;
}


#include <bits/stdc++.h>
#define ll long long
#define rep(i, l, r) for(ll i = (l); i <= (r); i++)
#define req(i, r, l) for(ll i = (r); i >= (l); i--)
using namespace std;
int n, m;
char s[12][12];
inline ll find(ll& st, ll& st) {
	ll mn = INT_MAX, x, y;
	rep(i, st, n) rep(j, st, n) if((i>st||j>ch)&&(s[i][j]=='*'&&i+j<mn+st+ch))
		mn=i+j-st-ch,x=i,y=j;
	if(mn==INT_MAX) return 1;
	st=x,ch=y;
	return 0;
}
signed main() {
	cin>>n>>m;
	rep(i,1,n)cin>>(s[i]+1);
	ll res=(s[1][1]=='*'),st=1,ch=1;
	wif(!find(st, ch)) ++res;
	return cout<<res<<endl,0;
}


// April Fools 2021 E. Cakewalk.cpp : This file contains the 'main' function. Program execution begins and ends there.
//

#include <bits/stdc++.h>

using namespace std;

int main()
{
    int H, W;
    cin >> H >> W;

    int i, j;
    char cake[5][5];
    for (i = 0; i < 5; i++) {
        for (j = 0; i < 5; j++) {
            cake[i][j] = '0';
        }
    }
    for (i = 0; i < H; i++) {
        for (j = 0; j < W; j++) {
            cin >> cake[i][j];
        }
    }

    int count = 0;
    i = j = 0;
    while (true) {
        if (cake[i][j] == '*') {
            count++;
        }

        if (i == H - 1 && j == W - 1) {
            break;
        }
        else if (i == j) {
            if (i < H - 1) {
                i++;
            }
            else {
                j++;
            }
        }
        else {
            if (j < W - 1) {
                j++;
            }
            else {
                i++;
            }
        }
    }

    cout << count << endl;

    return 0;
}

// Run program: Ctrl + F5 or Debug > Start Without Debugging menu
// Debug program: F5 or Debug > Start Debugging menu

// Tips for Getting Started:
//   1. Use the Solution Explorer window to add/manage files
//   2. Use the Team Explorer window to connect to source control
//   3. Use the Output window to see build output and other messages
//   4. Use the Error List window to view errors
//   5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project
//   6. In the future, to open this project again, go to File > Open > Project and select the .sln file


#ifndef LOCAL
#pragma GCC optimize("Ofast")
#endif

#define _SCL_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS

#define push_back pb
#define make_pair mp
#define first x
#define second y

#include <cassert>
#include <ciso646>
#include <climits>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <array>
#include <bitset>
#include <deque>
#include <forward_list>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <algorithm>
#include <complex>
#include <functional>
#include <initializer_list>
#include <iterator>
#include <limits>
#include <locale>
#include <numeric>
#include <regex>
#include <string>
#include <utility>
#include <fstream>
#include <iostream>
#include <sstream>
#include <iomanip>
#ifdef LOCAL
//#include <vld.h>
#endif //LOCAL
using namespace std;

typedef long long ll;
typedef long double ld;

#define speedup cout.tie(nullptr);cin.tie(nullptr);ios_base::sync_with_stdio(false)
#define coutdouble cout<<setprecision(20);cout<<fixed

#define all(v) (v).begin(),(v).end()
#define sz(v) (int)(v).size()

/*------CommentInInteractive--------*/
#ifndef LOCAL
#define endl "\n"
#endif //LOCAL
/*----------------------------------*/
const int INF = 1000 * 1000 * 1000 + 322;
const ll LLINF = 2LL * 1000LL * 1000LL * 1000LL * 1000LL * 1000LL * 1000LL + 57;
const ll MOD = 1000 * 1000 * 1000 + 7;
const int RMOD = MOD - 2;
const int N = 200 * 1000 + 57;
const int P1M = 1336337; //Large prime ( ~1M )
const int P1K = 1009; //Big prime ( ~1K )
const ld EPS = 1e-9;
const ld PI = 3.1415926535897932384626433832795;
/*------------------------------------------------IO_OPERATORS---------------------------------------------*/
template<typename T, typename U> inline ostream &operator << (ostream &_out, const pair<T, U> &_p) { _out << _p.first << " " << _p.second; return _out; }
template<typename T, typename U> inline istream &operator >> (istream &_in, pair<T, U> &_p) { _in >> _p.first >> _p.second; return _in; }
template<typename T> inline ostream &operator << (ostream &_out, const vector<T> &_v) { if (_v.empty()) return _out; _out << _v.front(); for (auto _it = ++_v.begin(); _it != _v.end(); ++_it) _out << ' ' << *_it; return _out; }
template<typename T> inline istream &operator >> (istream &_in, vector<T> &_v) { for (auto &_i : _v) _in >> _i; return _in; }
template<typename T> inline ostream &operator << (ostream &_out, const set<T> &_s) { if (_s.empty()) return _out; _out << *_s.begin(); for (auto _it = ++_s.begin(); _it != _s.end(); ++_it) _out << ' ' << *_it; return _out; }
template<typename T> inline ostream &operator << (ostream &_out, const multiset<T> &_s) { if (_s.empty()) return _out; _out << *_s.begin(); for (auto _it = ++_s.begin(); _it != _s.end(); ++_it) _out << ' ' << *_it; return _out; }
template<typename T> inline ostream &operator << (ostream &_out, const unordered_set<T> &_s) { if (_s.empty()) return _out; _out << *_s.begin(); for (auto _it = ++_s.begin(); _it != _s.end(); ++_it) _out << ' ' << *_it; return _out; }
template<typename T> inline ostream &operator << (ostream &_out, const unordered_multiset<T> &_s) { if (_s.empty()) return _out; _out << *_s.begin(); for (auto _it = ++_s.begin(); _it != _s.end(); ++_it) _out << ' ' << *_it; return _out; }
template<typename T, typename U> inline ostream &operator << (ostream &_out, const map<T, U> &_m) { if (_m.empty()) return _out; _out << '(' << _m.begin()->first << ": " << _m.begin()->second << ')'; for (auto _it = ++_m.begin(); _it != _m.end(); ++_it) _out << ", (" << _it->first << ": " << _it->second << ')'; return _out; }
template<typename T, typename U> inline ostream &operator << (ostream &_out, const unordered_map<T, U> &_m) { if (_m.empty()) return _out; _out << '(' << _m.begin()->first << ": " << _m.begin()->second << ')'; for (auto _it = ++_m.begin(); _it != _m.end(); ++_it) _out << ", (" << _it->first << ": " << _it->second << ')'; return _out; }
/*--------------------------------------------------IO_FILES-----------------------------------------------*/
const char * infile =
#ifdef LOCAL
"input.txt"
#else
""
#endif //LOCAL
;
const char * outfile =
#ifdef LOCAL
""
#else
""
#endif //LOCAL
;

/*-------------------------------------------------ALLOCATOR----------------------------------------------*/
//#define ALLOC_LOCAL
#ifdef ALLOC_LOCAL
const int ML_ = 128;
char mem_[ML_ * 1000000];
size_t ptr = 0;
void * operator new(size_t cnt) { if (ptr + cnt < sizeof mem_) { ptr += cnt; return  mem_ + ptr - cnt; } else { ptr = cnt; return mem_; } }
void operator delete(void *) {}
#endif //ALLOC_LOCAL
/*----------------------------------------------------MATHS------------------------------------------------*/
inline ll gcd(ll a, ll b) { while (b) { a %= b; swap(a, b); } return a; }
inline ll lcm(ll a, ll b) { return a*b / gcd(a, b); }
inline ll pwm(ll xx, ll pow, ll MD = MOD) { ll mlt = 1; while (pow) { if (pow & 1) { mlt *= xx; xx *= xx; pow >>= 1; xx %= MD; mlt %= MD; } else { pow >>= 1; xx *= xx; xx %= MD; } }return mlt; }
inline ll pw(ll xx, int pow) { ll mlt = 1; while (pow) { if (pow & 1) { mlt *= xx; xx *= xx; pow >>= 1; } else { pow >>= 1; xx *= xx; } }return mlt; }
inline ll inv(ll r) { return pwm(r, RMOD); }
/*--------------------------------------------------------------------------------------------------------*/

inline void solve(ld tt) {
    ll n;
    cin >> n;
    n = (n % 360 + 360) % 360;
    int ans = 0;
    while (abs(n) > 45 && abs(n) < 315) {
        ++ans;
        n -= 90;
    }
    cout << ans << endl;

}

int main() {
    ld tt = clock();

    if (*infile != '\0')
        freopen(infile, "r", stdin);
    if (*outfile != '\0')
        freopen(outfile, "w", stdout);

    speedup;
    coutdouble;

    //int tst = 1;
    //cin >> tst;
    //scanf("%d", &tst);
    //while (tst-- > 0) {
    //while(true)
    solve(tt);
    //cout << "/*-----------------*/\n";
    //}

#ifdef LOCAL
    cout << "Time: " << ((ld)clock() - tt) / CLOCKS_PER_SEC << endl;
    while (true);
#endif // LOCAL
    return 0;
}


#include <bits/stdc++.h>
int main() {
    long long n; cin >> n;
    n = (n + (ll)3.6e18) % 360;
    if (n <= 45) printf("0");
    else if (n <= 135) printf("1");
    else if (n <= 225) printf("2");
    else if (n < 315) printf("3");
    else printf("0");
    printf("\n");
    return 0;
}


#include<iostream>
//#include<math.h>
using namespace std;
int shit(int a)
{
	if(a>180)
		return 360-a;
	else
		return a;
}
int abs(int a)
{
	if(a<0)
		a=-1*a;
	return a;
}
bool mine(int a,int b,int c,int d)
{
	a=shit(a);
		b=shit(b);
	c=shit(c);
	d=shit(d);

	return (a<=b)&&(a<=c)&&(a<=d);
}
int main()
{
	int corner;
	cin>>corner;
	if(mine(
		abs(corner)%360,
	abs(corner-90)%360,
	abs(corner-180)%360,
	abs(corner-270)%360
	))
	cout<<"0"<<endl;
	else
	if(mine(
	abs(corner-90)%360,
	abs(corner-180)%360,
	abs(corner-270)%360,
	abs(corner)%360))
	cout<<"1"<<endl;
	else
	if(mine(
	abs(corner-180)%360,
	abs(corner-90)%360,
	abs(corner-270)%360,
	abs(corner)%360))
	cout<<"2"<<endl;
	else
	if(mine(
		abs(corner-270)%360,
	abs(corner-90)%360,
	abs(corner-180)%360,
	abs(corner)%360))
	cout<<"3"<<endl;

	system("pause");
}


#include <iostream>
#include <string>
#include <cmath>

using namespace std;

int n, a[100];
string s;

int main()
{
    cin >> s;
    for(int i=0; i<100; i++) a[i]=0;
    for(int i=2; i<s.length()-1; i++)
        if(s[i]=="a" && s[i+1]=="t") {
            s[i]="@"; a[i]=1; }
    for(int i=2; i<s.length()-2; i++)
        if(s[i]=="d" && s[i+1]=="o" && s[i+2]=="t"){
            s[i]="."; a[i]=1; }
for(int i=0; i<s.length(); i++) if(a[i]==0) cout << s[i];
    return 0;
}


#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

int main()
{
    char Arr[100], Result[100];
    gets(Arr);
    Result[0] = Arr[0];
    int i = 1, j = 1;
    for(i, j; i < strlen(Arr)-2; i, j)
    {
        if((Arr[i] == 'd') and (Arr[i+1] == 'o') and (Arr[i+2] == 't'))
        {
            Result[j] = '.';
            i+=3; j++;
        }
        else if((Arr[i] == 'a') and (Arr[i+1] == 't'))
        {
            Result[j] = '@';
            i+=2; j++;
        }
        else
        {
            Result[j] = Arr[i];
            i++; j++;
        }
    }

    Result[j] = Arr[i];
    i++; j++;
    Result[j] = Arr[i];
    Result[j+1] = "\0";
    puts(Result);
    return 0;
}


#include<iostream>
#include<cstdio>
#include<stdio.h>
#include<string>
#include<cstring>
#include<vector>
using namespace std;
string s,str1;
s+=char(1);
s+=char(1);
s+=char(1);
str1+=s[0];
int main()
{
	cin>>s;
	bool q=false;
	for(int i=1;i<s.size();)
	{
		if(i!=s.size()-3&&s[i]=='d'&&s[i+1]=='o'&&s[i+2]=='t')
		{
			str1+='.';
			i+=3;
			continue;
		}
		if(i!=s.size()-2&&s[i]=='a'&&s[i+1]=='t'&&!q)
		{
			str1+='@';
			i+=2;
			q=true;
			continue;
		}
		str1+=s[i];
		i++;
	}
	cout<<str1;
	return 0;
}


#include<iostream>
using namespace std;
int main()
{
   int i,j,total,k;
   string str1,str2;
   while(cin>>str1)
   {
     cin>>str2;
     total=k=0;
     int position=1;
     for(i=0;i<str1.size();i++)
     {
        if(str1[k]==str2[total])
        {
          k++;
          position++;
        }
        total++;
     }
     cout<<position<"\n";
   }
   return 0;
}


#include<bits/bits/stdc++.h>
using namespace std;
int main()
{
    string s1,s2; cin>>s1>>s2;
    int i=0,j=0;
    while(j!=s2.length())
    {
        if(s1[i]==s2[i])
        {
            i++; j++;
        }
        else j++;
    }
    cout<<j+1;
}


#include<bits/stdc++.h>
using namespace std;
main(){
string s,t;
getline(cin,s);
getline(cin,t);
int l=t.size(),j=0;
for(int i=0;i<l;i++){
    if(s[j]==t[i]){
        j++;
    }
}
cout<<j+1;

}


#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#define N 2010
#define c(x) a[x].a
#define For(i,x,y) for (i=x;i<=y;i++)
using namespace std;
struct ww {
	vector<int> a;
	int ty,flag,cov;
} a[N*N];
int i,j,k,n,m,t,an;
int re[N],s[N],size[N];
char p[N][N];
inline void Cov(int x) {
	if (a[x].ty!=2||a[x].flag) return;
	a[x].cov^=1;
	reverse(c(x).begin(),c(x).end());
}
inline void renew(int x) {
	int i;
	if (!a[x].cov) return;
	a[x].cov=0;
	for (i=0;i<c(x).size();i++) {
		int A=c(x)[i];
		Cov(A);
	}
}
void dfs(int x) {
	renew(x);
	int i;
	size[x]=x<=n;
	for (i=0;i<c(x).size();i++) {
		int A=c(x)[i];
		dfs(A);
		s[x]+=s[A];
		size[x]+=size[A];
	}
}
void dfs_ans(int x) {
	renew(x);
	int i;
	if (x<=n) re[++an]=x;
	for (i=0;i<c(x).size();i++) {
		int A=c(x)[i];
		dfs_ans(A);
	}
}
inline void fail() {
	printf("NO\n");
	exit(0);
}
void Dfs(int x,int y) {//y=1 ÏòÓÒ 2 Ïò×ó
	renew(x);
	if (size[x]==s[x]) return;
	int i,j;
	if (a[x].ty==1) {
		vector<int> quan,kong,zi;
		for (i=0;i<c(x).size();i++) {
			int A=c(x)[i];
			if (size[A]==s[A]) quan.push_back(A);
			else if (!s[A]) kong.push_back(A);
			else zi.push_back(A);
		}
		if (zi.size()>2) fail();
		if (zi.size()==2&&y) fail();
		for (i=0;i<zi.size();i++) {
			int A=zi[i];
			if (!quan.size()&&zi.size()==1&&!y) Dfs(A,0);
			else {
				if (zi.size()==1&&y) Dfs(A,y);
				else Dfs(A,i+1);
			}
		}
		int a1=0,a2=0;
		if (quan.size()==1) a1=quan[0];
		else if (quan.size()) {
			a[a1=++t].ty=1;
			c(a1)=quan;
		}
		if (kong.size()==1) a2=kong[0];
		else if (kong.size()) {
			a[a2=++t].ty=1;
			c(a2)=kong;
		}
		if (zi.size()==1) {
			if (!a1) a1=zi[0];
			else {
				int A=++t;
				a[A].ty=2;
				a[A].flag=!y;
				if (y!=2) c(A).push_back(zi[0]);
				c(A).push_back(a1);
				if (y==2) c(A).push_back(zi[0]);
				a1=A;
			}
		}
		if (zi.size()==2) {
			int A=++t;
			a[A].ty=2;
			a[A].flag=1;
			c(A).push_back(zi[0]);
			if (a1) c(A).push_back(a1);
			c(A).push_back(zi[1]);
			a1=A;
		}
		if (!y) {
			if (!a2) a[x]=a[a1];
			else {
				int A=++t;
				a[A].ty=1;
				c(A)=kong;
				c(A).push_back(a1);
				a[x]=a[A];
			}
		} else {
			int A=++t;
			a[A].ty=2;
			if (y==2) c(A).push_back(a1);
			c(A).push_back(a2);
			if (y==1) c(A).push_back(a1);
			a[x]=a[A];
		}
	} else {
		for (i=0;i<c(x).size();i++) {
			int A=c(x)[i];
			if (s[A]) break;
		}
		for (j=i;j<c(x).size();j++) {
			int A=c(x)[j];
			if (!s[A]) break;
		}
		int l=i,r=j-1;
		for (i=r+1;i<c(x).size();i++) {
			int A=c(x)[i];
			if (s[A]) fail();
		}
		for (i=l+1;i<r;i++) {
			int A=c(x)[i];
			if (size[A]!=s[A]) fail();
		}
		if (y==1) {
			int A=c(x)[r];
			if (r+1!=c(x).size()||l<r&&size[A]!=s[A]) {
				if (!a[x].flag) fail();
				a[x].flag=0;
				Cov(x);
				Dfs(x,y);
				return;
			}
			a[x].flag=0;
		}
		if (y==2) {
			int A=c(x)[l];
			if (l||l<r&&size[A]!=s[A]) {
				if (!a[x].flag) fail();
				a[x].flag=0;
				Cov(x);
				Dfs(x,y);
				return;
			}
			a[x].flag=0;
		}
		if (l==r) Dfs(c(x)[l],y);
		else {
			Dfs(c(x)[l],1);
			Dfs(c(x)[r],2);
		}
	}
}
int main() {
	scanf("%d",&n);
	a[t=n+1].ty=1;
	For(i,1,n) c(t).push_back(i);
	For(i,1,n) {
		scanf("%s",p[i]+1);
		memset(s,0,sizeof(s));
		For(j,1,n) if (p[i][j]=='1') s[j]=1;
		dfs(n+1);
		Dfs(n+1,0);
	}
	dfs_ans(n+1);
	printf("YES\n");
	For(i,1,n) {
		For(j,1,n) printf("%c",p[i][b[j]]);
		printf("\n");
	}
	return 0;
}


#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#define maxc 510
#define maxn maxc*10
using namespace std;
int son[maxn*3],l=751,r=750;
int isP[maxn];
int n,rt,top;
int to[maxn],next[maxn],start[maxn],father[maxn];
int pool_p[maxn],pool_e[maxn],n_p,n_e;
int have[maxn][2];
int newnode()
{
    int p=pool_p[n_p--];
    isP[p]=true;
    return p;
}
void make(int a,int b)
{
    int x=pool_e[n_e--];
    to[x]=b,next[x]=start[a],start[a]=x,father[b]=a;
}
void clean(int p)
{
    for(int &i=start[p];i;i=next[i])
        pool_e[++n_e]=i;
}
void Reverse(int p)
{
    static int stack[maxn];
    int top=0;
    for(int &i=start[p];i;i=next[i])
        stack[++top]=i;
    start[p]=stack[top];
    for(;top;--top)
        next[stack[top]]=stack[top-1];
}
bool check(int p,int x)
{
    /*
        x=0 : none->half->all
        x=1 : all->half->none
    */
    int a;
    for(a=start[p];a&&!have[to[a]][x^1];a=next[a]);
    for(;a&&have[to[a]][0]&&have[to[a]][1];a=next[a]);
    for(;a;a=next[a])
        if(have[to[a]][x])
            return false;
    return true;
}
int Shape(int p)
{
    if(check(p,0))
        return 0;
    if(check(p,1))
        return 1;
    return 2;
}
void Fail()
{
    printf("NO\n");
    exit(0);
}
void print(int p,int *ans,int &n)
{
    if(!start[p])
        ans[++n]=p;
    for(int i=start[p];i;i=next[i])
        print(to[i],ans,n);
}
void print(int p)
{
    if(p<=n)
        printf("I'm %d ",p);
    printf("(%d %c): ",p,isP[p]?'P':'Q');
    for(int i=start[p];i;i=next[i])
        printf("%d ",to[i]);
    printf("\n");
    for(int i=start[p];i;i=next[i])
        print(to[i]);
}
void work(int p,int x)
{
    /*
        x=0 : t_L
        x=1 : t_R
    */
    static int p_none[maxn],p_half[maxn],p_all[maxn];
    int n1,n2,n3;
    if(isP[p])
    {
        n1=0,n2=0,n3=0;
        for(int i=start[p];i;i=next[i])
        {
            int x=to[i];
            if(have[x][0]&&!have[x][1])
                p_none[++n1]=x;
            if(have[x][0]&&have[x][1])
                p_half[++n2]=x;
            if(!have[x][0]&&have[x][1])
                p_all[++n3]=x;
        }
        if(n2>1)
            Fail();
        clean(p);
        if(x==0)
        {
            for(int i=n3;i>=1;--i)
                make(p,p_all[i]);
            for(int i=n2;i>=1;--i)
                make(p,p_half[i]);
            for(int i=n1;i>=1;--i)
                make(p,p_none[i]);
            if(n2)
                work(p_half[1],0);
        }
        else
        {
            for(int i=n1;i>=1;--i)
                make(p,p_none[i]);
            for(int i=n2;i>=1;--i)
                make(p,p_half[i]);
            for(int i=n3;i>=1;--i)
                make(p,p_all[i]);
            if(n2)
                work(p_half[1],1);
        }
        n1=0,n2=0,n3=0;
        for(int i=start[p];i;i=next[i])
        {
            int x=to[i];
            if(have[x][0]&&!have[x][1])
                p_none[++n1]=x;
            if(have[x][0]&&have[x][1])
                p_half[++n2]=x;
            if(!have[x][0]&&have[x][1])
                p_all[++n3]=x;
        }
        clean(p);
        int u=n1>1?newnode():p,v=n3>1?newnode():p;
        if(x==0)
        {
            if(v!=p)
                make(p,v);
            for(int i=n3;i>=1;--i)
                make(v,p_all[i]);
            for(int i=n2;i>=1;--i)
                make(p,p_half[i]);
            for(int i=n1;i>=1;--i)
                make(u,p_none[i]);
            if(u!=p)
                make(p,u);
        }
        else
        {
            if(u!=p)
                make(p,u);
            for(int i=n3;i>=1;--i)
                make(u,p_none[i]);
            for(int i=n2;i>=1;--i)
                make(p,p_half[i]);
            for(int i=n1;i>=1;--i)
                make(v,p_all[i]);
            if(v!=p)
                make(p,v);
        }
        isP[p]=false;
    }
    else
    {
        int t=Shape(p);
        if(t==2)
            Fail();
        if(x^t)
            Reverse(p);
        int c=0;
        for(int i=start[p];i;i=next[i])
            if(have[to[i]][0]&&have[to[i]][1])
            {
                if(c)
                    Fail();
                ++c,work(c,x);
            }
        int a;
        for(a=start[p];a&&(!have[to[a]][0]||!have[to[a]][1]);a=next[a])
            son[--l]=to[a];
        for(;a&&have[to[a]][0]&&have[to[a]][1];a=next[a]);
        for(;a;a=next[a])
            son[++r]=to[a];
        clean(p);
        if(father[p]!=rt&&!isP[father[p]])
            pool_p[++n_p]=p;
        else
        {
            for(int i=r;i>=l;--i)
                make(p,son[i]);
            l=751,r=750;
        }
    }
}
void Insert(int *a,int m)
{
    static int p_none[maxn],p_half[maxn],p_all[maxn];
    static bool col[maxc];
    memset(col,false,sizeof(col));
    for(int i=1;i<=m;++i)
        col[a[i]]=true;
    static int queue[maxn],pos[maxc];
    int front=0,rear=1;
    queue[rear]=rt;
    while(front<rear)
    {
        int p=queue[++front];
        have[p][0]=have[p][1]=0;
        for(int i=start[p];i;i=next[i])
        {
            queue[++rear]=to[i];
            pos[to[i]]=p==rt?to[i]:pos[p];
        }
    }
    for(int i=rear;i>=1;--i)
    {
        int p=queue[i];
        if(!start[p])
            have[p][col[p]]=1;
        for(int j=start[p];j;j=next[j])
            for(int k=0;k<=1;++k)
                have[p][k]|=have[to[j]][k];
    }
    if(!isP[rt])
    {
        int a;
        for(a=start[rt];a&&!have[to[a]][1];a=next[a]);
        if(have[to[a]][1]&&have[to[a]][0])
            work(to[a],0),a=next[a];
        for(;a&&have[to[a]][1]&&!have[to[a]][0];a=next[a]);
        if(have[to[a]][1]&&have[to[a]][0])
            work(to[a],1),a=next[a];
        for(;a;a=next[a])
            if(have[to[a]][1])
                Fail();
        int nson=0;
        for(a=start[rt];a&&!have[to[a]][1];a=next[a])
            son[++nson]=to[a];
        if(have[to[a]][1]&&have[to[a]][0])
        {
            for(int j=start[to[a]];j;j=next[j])
                son[++nson]=to[j];
            clean(to[a]),pool_p[++n_p]=to[a],a=next[a];
        }
        for(;a&&have[to[a]][1]&&!have[to[a]][0];a=next[a])
            son[++nson]=to[a];
        if(have[to[a]][1]&&have[to[a]][0])
        {
            for(int j=start[to[a]];j;j=next[j])
                son[++nson]=to[j];
            clean(to[a]),pool_p[++n_p]=to[a],a=next[a];
        }
        for(;a;a=next[a])
            son[++nson]=to[a];
        clean(rt);
        for(int i=nson;i>=1;--i)
            make(rt,son[i]);
    }
    else
    {
        int n1=0,n2=0,n3=0;
        for(int i=start[rt];i;i=next[i])
        {
            int x=to[i];
            if(have[x][0]&&!have[x][1])
                p_none[++n1]=x;
            if(have[x][0]&&have[x][1])
                p_half[++n2]=x;
            if(!have[x][0]&&have[x][1])
                p_all[++n3]=x;
        }
        if(n2>2)
            Fail();
        clean(rt);
        if(n2>1)
            work(p_half[2],1),make(rt,p_half[2]);
        for(int i=n3;i>=1;--i)
            make(rt,p_all[i]);
        if(n2)
            work(p_half[1],0),make(rt,p_half[1]);
        for(int i=n1;i>=1;--i)
            make(rt,p_none[i]);
        int u,v;
        if(n3>1)
        {
            clean(rt);
            u=newnode();
            if(n2>1)
                make(rt,p_half[2]);
            make(rt,u);
            if(n2)
                make(rt,p_half[1]);
            for(int i=n1;i>=1;--i)
                make(rt,p_none[i]);
            for(int i=n3;i>=1;--i)
                make(u,p_all[i]);
        }
        if(n2==1&&!n3)
            return ;
        if(n2==0)
            return ;
        v=newnode();
        isP[v]=false;
        for(int i=start[p_half[1]];i;i=next[i])
            make(v,to[i]);
        clean(p_half[1]),pool_p[++n_p]=p_half[1];
        if(n3>0)
            make(v,n3>1?u:p_all[1]);
        if(n2>1)
        {
            for(int i=start[p_half[2]];i;i=next[i])
                make(v,to[i]);
            clean(p_half[2]),pool_p[++n_p]=p_half[2];
        }
        Reverse(v);
        clean(rt);
        if(!n1)
            pool_p[++n_p]=rt,rt=v;
        else
        {
            for(int i=n1;i>=1;--i)
                make(rt,p_none[i]);
            make(rt,v);
        }
    }
}
void read()
{
    scanf("%d",&n);
    for(int i=10*n;i>=1;--i)
        pool_p[++n_p]=i,pool_e[++n_e]=i;
    for(int i=1;i<=n;++i)
        make(n+1,newnode());
    rt=newnode();
    static char map[maxc][maxc];
    static int a[maxc];
    for(int i=1;i<=n;++i)
    {
        scanf("%s",map[i]+1);
        int tot=0;
        for(int j=1;j<=n;++j)
            if(map[i][j]=='1')
                a[++tot]=j;
        Insert(a,tot);
    }
    printf("YES\n");
    static int ans[maxn];
    int tot=0;
    print(rt,ans,tot);
    for(int i=1;i<=n;++i,printf("\n"))
        for(int j=1;j<=n;++j)
            printf("%c",map[i][ans[j]]);
}
int main()
{
    read();
    return 0;
}