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