2010 Asia Hangzhou/Fuzhou Regional Contest

hdu3681 Prison Break

二分+状压DP...

因为懒得写dx和dy导致BFS完全写错...过了样例查不出错 = = 

怒而重写BFS就过了,虽然还是没有写dxdy

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <list>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
//#pragma comment(linker, "/STACK:16777216")
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define N 20
int n , m , num[N][N] , t[N] , cnt , g[N][N];
char s[N][N];

void BFS(int id , int x)
{
  int i , j , y , d[N][N];
  for (i = 0 ; i < n ; ++ i)
    for (j = 0 ; j < m ; ++ j)
      d[i][j] = 1 << 30; d[x / m][x % m] = 0;
  queue<pair<int ,int> > Q; Q.push(mp(x / m , x % m));
  while (!Q.empty()){
    x = Q.front().fi , y = Q.front().se ; Q.pop();
    if (x && s[x - 1][y] != 'D' && d[x - 1][y] == 1 << 30)
      d[x - 1][y] = d[x][y] + 1 , Q.push(mp(x - 1 , y));
    if (y && s[x][y - 1] != 'D' && d[x][y - 1] == 1 << 30)
      d[x][y - 1] = d[x][y] + 1 , Q.push(mp(x , y - 1));
    if (x < n - 1 && s[x + 1][y] != 'D' && d[x + 1][y] == 1 << 30)
      d[x + 1][y] = d[x][y] + 1 , Q.push(mp(x + 1 , y));
    if (y < m - 1 && s[x][y + 1] != 'D' && d[x][y + 1] == 1 << 30)
      d[x][y + 1] = d[x][y] + 1 , Q.push(mp(x , y + 1));
  }
  for (i = 0 ; i < cnt ; ++ i)
    g[id][i] = d[t[i] / m][t[i] % m];
}

int f[1 << 15][15];
void work()
{
  int i , j , k , l , r , val , res = 0 , ans , st;
  for (i = 0 ; i < n ; ++ i)
    scanf("%s" , s[i]);
  k = cnt = 0;
  for (i = 0 ; i < n ; ++ i)
    for (j = 0 ; j < m ; ++ j)
    {
      if (s[i][j] == 'F')
        st = cnt;
      if (s[i][j] == 'Y')
        res |= (1 << cnt);
      if (s[i][j] != 'D' && s[i][j] != 'S')
        t[cnt ++] = k;
      num[i][j] = k ++;
    }
  for (i = 0 ; i < cnt ; ++ i)
    BFS(i , t[i]);

  l = 0 , r = n * m;
  while (l < r)
  {
    val = (l + r) >> 1;
    memset(f , -1 , sizeof(f));
    f[1 << st][st] = val , ans = -1;
    for (i = 1 ; i < 1 << cnt ; ++ i)
    {
      for (j = 0 ; j < cnt ; ++ j) if (f[i][j] >= 0)
      {
        if ((i & res) == res)
          ans = max(ans , f[i][j]);
        for (k = 0 ; k < cnt ; ++ k) if (~i & (1 << k))
        {
          if (g[j][k] <= f[i][j])
          {
            f[i | (1 << k)][k] = max(f[i | (1 << k)][k] , f[i][j] - g[j][k]);
            if (~res & (1 << k))
              f[i | (1 << k)][k] = val;
          }
        }
      }
    }
    if (ans >= 0)
      r = val;
    else l = val + 1;
  }
  if (l == n * m)
    l = -1;
  printf("%d\n" , l);
}

int main()
{
  std::ios::sync_with_stdio(false);
  //int _; scanf("%d",&_); while (_--)
  while (scanf("%d%d",&n,&m) , n || m)
    work();
  return 0;
}

hdu3686 Traffic Real Time Query System

坑的题啊!

Tarjan缩点之后,把BCC都连在对应的割点上,最后形成了一棵割点和BCC交错的树,询问就是两个BCC之间的路径有多少割点,其实就是路径长度/2。

思路很清晰,然后WAWAWAWAWA....

对拍全对找不到错,然后WAWAWAWAWA...

对拍数据里面很良心都没有重边...我就琢磨是不是这个问题..

然后回题面上一看人家也没说没有重边……

把tarjan改了小小的下让它能处理重边,就AC了……一下午的时间加WAx33...._(:3」∠)_

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <list>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#pragma comment(linker, "/STACK:16777216")
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define N 200005
#define M 500005

int n , m , pre[N] , mcnt , id[N];
struct edge
{
  int x , next;
}e[M] , g[M << 1];
int pp[N] , cc;

int low[N] , DFN[N] , ncnt , bel[M] , bcnt , cutnum , pel[M];
vector<int> bcc[N];
bool iscut[N];

stack< pair<int,int> > S;

void tarjan(int x , int fa)
{
  low[x] = DFN[x] = ++ ncnt;
  int i , y , xx , yy , child = 0;
  for (i = pre[x] ; ~i ; i = e[i].next)
  {
    y = e[i].x;
    if (!DFN[y])
    {
      S.push(mp(x , i ^ 1));
      ++ child;
      tarjan(y , i);
      low[x] = min(low[x] , low[y]);
      if (low[y] >= DFN[x])
      {
        iscut[x] = 1;
        ++ bcnt , bcc[bcnt].clear();
        do
        {
          xx = S.top().fi , yy = e[S.top().se].x , pel[(S.top().se >> 1) + 1] = bcnt ,  S.pop();
          if (bel[xx] != bcnt) bcc[bcnt].pb(xx) , bel[xx] = bcnt;
          if (bel[yy] != bcnt) bcc[bcnt].pb(yy) , bel[yy] = bcnt;
        }while(x != xx || y != yy);
      }
    }
    else if (DFN[y] < DFN[x] && i != fa)
      S.push(mp(x , i)) , low[x] = min(DFN[y] , low[x]);
  }
  if (fa < 0 && child == 1) iscut[x] = 0;
}

int f[N][20] , L[N];
bool vis[N];

void dfs(int x , int fa)
{
  f[x][0] = fa , L[x] = L[fa] + 1 , vis[x] = 1;
  for (int i = pp[x] ; ~i ; i = g[i].next)
    if (!vis[g[i].x])
      dfs(g[i].x , x);
}
int LCA(int x , int y)
{
  int log , i; if (x == y) return x;
  if (L[x] < L[y]) swap(x , y);
  for (log = 1 ; (1 << log) <= L[x] ; ++ log); -- log;
  for (i = log ; i >= 0 ; -- i)
    if (L[x] - (1 << i) >= L[y])
      x = f[x][i];
  if (x == y) return y;
  for (i = log ; i >= 0 ; -- i)
    if (f[x][i] && f[y][i] && f[x][i] != f[y][i])
      x = f[x][i] , y = f[y][i];
  return f[x][0];
}

void work()
{
  int i , j , x , y , z;
  memset(pre , -1 , sizeof(pre));
  memset(pp , -1 , sizeof(pp));
  mcnt = bcnt = ncnt = cc = 0 ;
  while (m --)
  {
    scanf("%d%d",&x,&y);
    e[mcnt].x = y , e[mcnt].next = pre[x] , pre[x] = mcnt ++;
    e[mcnt].x = x , e[mcnt].next = pre[y] , pre[y] = mcnt ++;
  }
  memset(low , 0 , sizeof(low));
  memset(DFN , 0 , sizeof(DFN));
  memset(iscut , 0 , sizeof(iscut));
  memset(bel , 0 , sizeof(bel));
  memset(L , 0 , sizeof(L));
  memset(id , 0 , sizeof(id));
  memset(pel , 0 , sizeof(pel));

  for (i = 1 ; i <= n ; ++ i)
    if (!DFN[i])
      tarjan(i , -1);

  cutnum = bcnt;
  for (i = 1 ; i <= n ; ++ i)
    if (iscut[i])
      id[i] = ++ cutnum;
  for (j = 1 ; j <= bcnt ; ++ j)
  {
    for (i = 0 ; i < bcc[j].size() ; ++ i)
      if (iscut[y = bcc[j][i]])
      {
        y = id[y] , x = j;
        //cout << x << ' ' << y << endl;
        g[cc].x = y , g[cc].next = pp[x] , pp[x] = cc ++;
        g[cc].x = x , g[cc].next = pp[y] , pp[y] = cc ++;
      }
  }

  memset(f , 0 , sizeof(f));
  memset(vis , 0 , sizeof(vis));

  for (i = 1 ; i <= cutnum ; ++ i)
    if (!vis[i])
      dfs(i , 0);
  for (j = 1 ; 1 << j <= cutnum ; ++ j)
    for (i = 1 ; i <= cutnum ; ++ i)
      f[i][j] = f[f[i][j - 1]][j - 1];
  scanf("%d",&m);
  while (m --)
  {
    scanf("%d%d",&x ,&y);
    x = pel[x] , y = pel[y];
    //cout << x << ' ' << y << endl;
    z = LCA(x , y);
    printf("%d\n" , (L[x] + L[y] - L[z] - L[z]) >> 1);
  }
  //cout << endl;
}

int main()
{
  while (scanf("%d%d",&n,&m) , n || m)
    work();
  return 0;
}

hdu3689  Infinite monkey theorem 

KMP处理一下状态转移就可以直接DP了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <list>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#pragma comment(linker, "/STACK:16777216")
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define N 25

int n ,  m;
double p[N] , d[1001][N];
char str[N] , s[N];
int f[N];
void work()
{
  int i , j , k , l; double x , y;
  memset(p , 0 , sizeof(p));
  for (i = 1 ; i <= n ; ++ i)
  {
    scanf("%s %lf" , str , &x);
    p[*str - 'a'] = x;
  }
  scanf("%s" , s);
  n = strlen(s);
  f[0] = f[1] = 0;
  for (i = 1 ; i < n ;i ++)
  {
    int j = f[i];
    while (j && s[i] != s[j]) j = f[j];
    f[i + 1] = s[i] == s[j] ? j + 1 : 0;
  }
  memset(d , 0 , sizeof(d));
  d[0][0] = 1;

  for (i = 0 ; i < m ; ++ i)
  {
    for (j = 0 ; j < n ; ++ j) if (d[i][j] > 0)
    {
      for (k = 0 ; k < 26 ; ++ k) if (p[k] > 0)
      {
        l = j;
        while (l && k != s[l] - 'a') l = f[l];
        if (k == s[l] - 'a') ++ l;
        d[i + 1][l] += d[i][j] * p[k];
      }
    }
    d[i + 1][n] += d[i][n];
  }
  printf("%.2f%%\n" , d[m][n] * 100 + 1e-9);


}

int main()
{
  //std::ios::sync_with_stdio(false);
  //int _; scanf("%d",&_); while (_--)
  while (scanf("%d%d",&n,&m) , n || m)
    work();
  return 0;
}

hdu3691 Nubulsa Expo

全局最小割,源点没有意义。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <list>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#pragma comment(linker, "/STACK:16777216")
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define N 305
#define M 500005
int n , m , d[N] , g[N][N] , ans;
bool f[N] , u[N];

void find(int& s , int& t)
{
  int i , j , x;
  memset(u , 0 , sizeof(u));
  memset(d , 0, sizeof(d));
  for (i = 0 ;i < n ; ++ i)
  {
    x = -1;
    for (j = 0 ;j < n ;j ++)
      if (!u[j] && !f[j] && (d[j] > d[x] || x == -1))
        x = j;
    if (x == -1) {ans = min(ans , t == -1 ?  1 << 30 : d[t]); return;}
    u[x] = 1 , s = t , t = x;
    for (j = 0 ;j < n ;j ++)
      if (!u[j] && !f[j])
        d[j] += g[x][j];
  }
  ans = min(ans , d[t]);
}

void work()
{
  int i , j , x , y , z; ans = 1 << 30;
  memset(g , 0, sizeof(g));
  for (i = 1 ; i <= m ;i ++)
  {
    scanf("%d%d%d",&x,&y,&z);
    -- x , -- y;
    g[x][y] += z , g[y][x] += z;
  }
  memset(f , 0, sizeof(f));
  for (i = 1 ; i < n ;i ++)
  {
    x = y = -1 , find(x , y);
    f[y] = 1;
    for (j = 0 ; j < n ; ++ j)
      g[x][j] += g[y][j] , g[j][x] += g[j][y];
  }
  cout << ans << endl;
}

int main()
{
  //std::ios::sync_with_stdio(false);
  while (scanf("%d%d%d",&n,&m ,&ans) , n || m)
    work();
  return 0;
}


hdu3695 Computer Virus on Planet Pandora
文本串可以直接暴力展开,剩下的就是AC自动机了
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <list>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#pragma comment(linker, "/STACK:16777216")
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define N 250000
#define M 500005
char str[5100005] , tmp[5100005];
int ans;
bool bel[255];
struct ACautom
{
  int sum;
  int u[N][26];
  int v[N] , f[N] , l[N];
  void clear()
  {
    sum = 1 , v[0] = 0;
    memset(u[0] , 0 , sizeof(u[0]));
  }
  void insert(int k)
  {
    int x = 0 ;
    for (int i = 0 ; str[i] ; i ++)
    {
      int c = str[i] - 'A';
      if (!u[x][c])
      {
        memset(u[sum] , 0 , sizeof(u[sum]));
        v[sum] = 0;
        u[x][c] = sum ++;
      }
      x = u[x][c];
    }
    v[x] = k;
  }
  void getFail()
  {
    queue<int> q;
    f[0] = 0;
    for (int i = 0 ; i < 26 ; i ++)
    {
      int x = u[0][i];
      if (x) f[x] = 0 , q.push(x) , l[x] = 0;
    }
    while (!q.empty())
    {
      int x = q.front() ; q.pop();
      for (int i = 0 ; i < 26 ; ++ i)
        if (u[x][i])
        {
          int y = u[x][i];
          q.push(y);
          int j = f[x];
          while (j && !u[j][i]) j = f[j];
          f[y] = u[j][i];
          l[y] = v[f[y]] ? f[y] : l[f[y]];
        }
    }
  }
  void print(int i , int j)
  {
    if (j)
    {
      if (!bel[v[j]])
        bel[v[j]] = 1 , ++ ans;
      print(i , l[j]);
    }
  }

  void find()
  {
    int j = 0;
    for (int i = 0 ; str[i] ; ++ i)
    {
      int c = str[i] - 'A';
      while (j && !u[j][c]) j = f[j];
      j = u[j][c];
      if (v[j] && !bel[v[j]]) print(i , j);
      else if (l[j] && !bel[v[l[j]]]) print(i , l[j]);
    }
  }
}t;
int n ;

void work()
{
  int i , j , x , len = 0;
  scanf("%d",&n);
  t.clear();
  for (i = 1 ; i <= n ; ++ i)
    scanf("%s" , str) , t.insert(i);
  t.getFail();
  scanf("%s" , tmp);
  memset(bel , 0 , sizeof(bel)) , ans = 0;
  for (i = 0 ; tmp[i] ; ++ i)
  {
    if (tmp[i] == '[')
    {
      x = 0;
      for (j = i + 1 ; isdigit(tmp[j]) ; ++ j)
        x = x * 10 + tmp[j] - '0';
      while (x --) str[len ++] = tmp[j];
      i = ++ j;
    }
    else str[len ++] = tmp[i];
  }
  str[len] = 0;
  t.find();
  reverse(str , str + len);
  t.find();
  printf("%d\n" , ans);
}

int main()
{
  int _; scanf("%d",&_); while (_--)
    work();
  return 0;
}

hdu3696 Farm Game

给出的是一个DAG,逆向建图可以DP出每个物品可以卖出的最大单价。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <list>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#pragma comment(linker, "/STACK:16777216")
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define N 50005
#define M 100005
int n , m , pre[N] , mcnt , d[N];
struct edge
{
  int x ; double w; int next;
}e[M];
double p[N] , w[N];

void work()
{
  int i , x , y; double z;
  for (i = 1 ; i <= n ; ++ i)
    scanf("%lf%lf" , &p[i] , &w[i]);
  memset(pre , -1 , sizeof(pre)) , mcnt = 0;
  scanf("%d",&m);
  while (m --)
  {
    scanf("%d%d",&i,&x), -- i;
    while (i --)
    {
      scanf("%lf%d" , &z , &y);
      e[mcnt] = (edge){x , z , pre[y]} , pre[y] = mcnt ++ , ++ d[x];
      x = y;
    }
  }

  double ans = 0;
  queue<int> Q;
  for (i = 1 ; i <= n ; ++ i)
    if (!d[i]) Q.push(i);
  while (!Q.empty())
  {
    x = Q.front() , Q.pop();
    ans += p[x] * w[x];
    for (i = pre[x] ; ~i ; i = e[i].next)
    {
      y = e[i].x , z = e[i].w;
      p[y] = max(p[y] , p[x] * z);
      if (!-- d[y]) Q.push(y);
    }
  }
  printf("%.2f\n" , ans);
}

int main()
{
  //std::ios::sync_with_stdio(false);
  //int _; scanf("%d",&_); while (_--)
  while (scanf("%d" , &n) , n)
    work();
  return 0;
}

hdu3697 Selecting courses

范围很良心..可以直接暴力贪心,每次选择能选择的结束时间最小的课程。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <list>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#pragma comment(linker, "/STACK:16777216")
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define N 1005
#define M 100005
int n;
pair<int , int> a[N];
bool f[N];
void work()
{
  int i , j , k , sum , ans = 0 , x;
  for (i = 1 ; i <= n ; ++ i)
    scanf("%d%d",&a[i].fi , &a[i].se);
  for (k = 0 ; k < 5 ; ++ k) //[)
  {
    memset(f , 0 , sizeof(f)) , sum = 0;
    for (j = k ; j <= 1000 ; j += 5)
    {
      x = -1;
      for (i = 1 ; i <= n ; ++ i)
        if (!f[i] && a[i].fi <= j && j < a[i].se)
        {
          if (x == -1 || a[x].se > a[i].se)
            x = i;
        }
      if (~x) ++ sum , f[x] = 1;
    }
    ans = max(sum , ans);
  }
  printf("%d\n" , ans);
}

int main()
{
  //std::ios::sync_with_stdio(false);
  //int _; scanf("%d",&_); while (_--)
  while (scanf("%d" , &n) , n)
    work();
  return 0;
}

hdu3698 Let the light guide us

DP,然后拿线段树优化一下转移。

这样写是不是有点太暴力了……导致常数巨大一直TLE

尝试了一下读入优化,就过了QAQ……不管了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <list>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#pragma comment(linker, "/STACK:16777216")
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define N 5005
#define M 105

int n , m , a[M][N] , f[M][N];
int id(int l , int r) {return l + r | l != r;}
#define ID id(l , r)
#define MID int mid = (l + r) >> 1
#define Left l , mid
#define Right mid + 1 , r
pair<int , int> t1[N << 1] , t2[N << 1];
pair<int , int> *cur = t1 , *past = t2;
void buildtree(pair<int , int>* t , int l , int r)
{
  t[ID] = make_pair(1 << 30 , 1 << 30);
  if (l != r){
    MID ; buildtree(t , Left) , buildtree(t , Right);}
}

void pushup(pair<int , int>* t , int l , int r)
{
  MID; int p = ID , LL = id(Left) , RR = id(Right);
  t[p].fi = min(t[LL].fi , t[RR].fi);
}
void pushdown(pair<int , int>* t , int l , int r)
{
  if (t[ID].se == 1 << 30) return;
  MID; int p = ID , LL = id(Left) , RR = id(Right);
  t[LL].fi = min(t[LL].fi , t[p].se) , t[LL].se = min(t[LL].se , t[p].se);
  t[RR].fi = min(t[RR].fi , t[p].se) , t[RR].se = min(t[RR].se , t[p].se);
  t[p].se = 1 << 30;
}
void update(pair<int , int>* t , int l , int r , int top , int bot , int w)
{
  if (top <= l && r <= bot){ int p = ID;
    t[p].fi = min(t[p].fi , w) , t[p].se = min(t[p].se , w); return;}
  pushdown(t , l , r) ; MID;
  if (top <= mid) update(t , Left , top , bot , w);
  if (bot  > mid) update(t , Right , top , bot , w);
  pushup(t , l , r);
}

int query(pair<int , int>* t , int l , int r , int top , int bot)
{
  if (top <= l && r <= bot) return t[ID].fi;
  pushdown(t , l , r) ; MID; int res = 1 << 30;
  if (top <= mid) res = min(query(t , Left , top , bot) , res);
  if (bot  > mid) res = min(query(t , Right , top , bot) ,res);
  pushup(t , l , r); return res;
}
void RD(int& x)
{
  x = 0; char c;
  for (c = getchar() ;!isdigit(c) ; c = getchar()); x = c - '0';
  for (c = getchar() ; isdigit(c) ; c = getchar()) x = x * 10 + c - '0';
}
void work()
{
  int i , j , l , r , x;
  for (i = 1 ; i <= n ; ++ i)
    for (j = 1 ; j <= m ; ++ j)
      RD(a[i][j]);
  for (i = 1 ; i <= n ; ++ i)
    for (j = 1 ; j <= m ; ++ j)
      RD(f[i][j]);
  cur = t1 , past = t2;
  update(past , 1 , m , 1 , m , 0);
  for (i = 1 ; i <= n ; ++ i)
  {
    buildtree(cur , 1 , m);
    for (j = 1 ; j <= m ; ++ j)
    {
      l = max(1 , j - f[i][j]) , r = min(m , j + f[i][j]);
      x = query(past , 1 , m , l , r) + a[i][j];
      update(cur , 1 , m , l , r , x);
    }
    swap(past , cur);
  }
  printf("%d\n" , query(past , 1 , m , 1 , m));
}

int main()
{
  while (RD(n) , RD(m) , n || m)
    work();
  return 0;
}

hdu3699 A hard Aoshu Problem

枚举!挺好玩的题……

要注意就是除是带小数的除,除数不能为0,每个字母代表的数字都不一样。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <list>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
//#pragma comment(linker, "/STACK:16777216")
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define N 15

char s1[N] , s2[N] , s3[N];
int power[N] , a[N] , ans;
bool f[N];

void cal()
{
  int i , j , x = 0 , y = 0 , z = 0;
  for (i = 0 ; i < 5 ; ++ i) if (f[i]) for (j = i + 1 ; j < 5 ; ++ j) if (f[j] && a[i] == a[j]) return;
  for (i = 0 ; s1[i] ; ++ i) x = x * 10 + a[s1[i] - 'A'];
  for (i = 0 ; s2[i] ; ++ i) y = y * 10 + a[s2[i] - 'A'];
  for (i = 0 ; s3[i] ; ++ i) z = z * 10 + a[s3[i] - 'A'];
  if (strlen(s1) > 1 && !a[s1[0] - 'A']) return;
  if (strlen(s2) > 1 && !a[s2[0] - 'A']) return;
  if (strlen(s3) > 1 && !a[s3[0] - 'A']) return;
  if (x + y == z) ++ ans; //, printf("%d+%d=%d\n" , x ,y , z);
  if (x - y == z) ++ ans; //, printf("%d-%d=%d\n" , x ,y , z);
  if (x * y == z) ++ ans; //, printf("%d*%d=%d\n" , x ,y , z);
  if (y && x == y * z) ++ ans; //, printf("%d/%d=%d\n" , x ,y , z);
}

void work()
{
  int i , j; ans = 0;
  scanf("%s%s%s",s1,s2,s3);
  memset(f , 0 , sizeof(f));
  for (i = 0 ; s1[i] ; ++ i) f[s1[i] - 'A'] = 1;
  for (i = 0 ; s2[i] ; ++ i) f[s2[i] - 'A'] = 1;
  for (i = 0 ; s3[i] ; ++ i) f[s3[i] - 'A'] = 1;

  for (a[0] = 0 ; a[0] <= 9 * f[0] ; ++ a[0])
    for (a[1] = 0 ; a[1] <= 9 * f[1] ; ++ a[1])
      for (a[2] = 0 ; a[2] <= 9 * f[2] ; ++ a[2])
        for (a[3] = 0 ; a[3] <= 9 * f[3] ; ++ a[3])
          for (a[4] = 0 ; a[4] <= 9 * f[4] ; ++ a[4])
            cal();
  printf("%d\n" , ans);
}


int main()
{
  int _; scanf("%d",&_); while (_--)
    work();
  return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值