#include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; const int MOD = 20140927; struct Matrix{ int mat[2][2]; void init(){ memset(mat,0,sizeof(mat)); } Matrix operator *(const Matrix &b)const{ Matrix ret; for(int i = 0;i < 2;i++) for(int j = 0;j < 2;j++){ ret.mat[i][j] = 0; for(int k = 0;k < 2;k++){ ret.mat[i][j] += (long long)mat[i][k]*b.mat[k][j]%MOD; if(ret.mat[i][j] >= MOD) ret.mat[i][j] -= MOD; } } return ret; } void output(){ printf("%d %d\n%d %d\n",mat[0][0],mat[0][1],mat[1][0],mat[1][1]); } }; Matrix pow_M(Matrix A,int n){ Matrix ret; ret.mat[0][0] = ret.mat[1][1] = 1; ret.mat[0][1] = ret.mat[1][0] = 0; Matrix tmp = A; while(n){ if(n&1)ret = ret*tmp; tmp = tmp*tmp; n >>= 1; } return ret; } Matrix A[11*11*11 + 100]; vectorvec; Matrix B; Matrix C; struct Matrix2{ int mat[2][2]; void init(){ memset(mat,0,sizeof(mat)); } Matrix2 operator *(const Matrix2 &b)const{ Matrix2 ret; for(int i = 0;i < 2;i++) for(int j = 0;j < 2;j++){ ret.mat[i][j] = 0; for(int k = 0;k < 2;k++) if(mat[i][k] && b.mat[k][j]) ret.mat[i][j] = 1; } return ret; } }; Matrix2 pow_M(Matrix2 A,int n){ Matrix2 ret; ret.mat[0][0] = ret.mat[1][1] = 1; ret.mat[0][1] = ret.mat[1][0] = 0; Matrix2 tmp = A; while(n){ if(n&1)ret = ret*tmp; tmp = tmp*tmp; n >>= 1; } return ret; } Matrix2 A2[11*11*11 + 100]; Matrix2 B2; Matrix2 C2; void Add(int &a,int b){ if(a || b)a = 1; } int main() { for(int i = 0;i < 11*11*11;i++)A[i].init(); for(int i = 0;i < 11*11*11;i++)A2[i].init(); for(int x = 0;x < 11;x++) for(int y = 0;y < 11;y++) for(int z = 0; z < 11;z++){ int id = x*11*11 + y*11 + z; for(int i = 0;i < 10;i++){ if(x != 10 && x != i)continue; for(int j = 0;j < 10;j++){ if(y != 10 && y != j)continue; for(int k = 0;k < 10;k++){ if(z != 10 && z != k)continue; if(i + j == k)A[id].mat[0][0]++; if(i + j == 10 + k)A[id].mat[0][1]++; if(i + j + 1 == k)A[id].mat[1][0]++; if(i + j + 1 == 10 + k)A[id].mat[1][1]++; if(i + j == k)Add(A2[id].mat[0][0],1); if(i + j == 10 + k)Add(A2[id].mat[0][1],1); if(i + j + 1 == k)Add(A2[id].mat[1][0],1); if(i + j + 1 == 10 + k)Add(A2[id].mat[1][1],1); } } } } int T; int iCase = 0; int n1,m1,n2,m2,n3,m3; scanf("%d",&T); while(T--){ iCase++; scanf("%d%d",&n1,&m1); assert(n1 >= 1 && n1 <= 10000000); assert(m1 >= 0 && m1 <= n1); mapmp1; mapmp2; mapmp3; bool flag = true; vec.clear(); int id,x; while(m1--){ scanf("%d%d",&id,&x); id = n1 - 1 - id; vec.push_back(id); if(mp1.find(id) != mp1.end()){ if(mp1[id] != x)flag = false; } else mp1[id] = x; } scanf("%d%d",&n2,&m2); assert(n2 >= 1 && n2 <= 10000000); assert(m2 >= 0 && m2 <= n2); while(m2--){ scanf("%d%d",&id,&x); id = n2 - 1 - id; vec.push_back(id); if(mp2.find(id) != mp2.end()){ if(mp2[id] != x)flag = false; } else mp2[id] = x; } scanf("%d%d",&n3,&m3); assert(n3 >= 1 && n3 <= 10000000); assert(m3 >= 0 && m3 <= n3); while(m3--){ scanf("%d%d",&id,&x); id = n3 - 1 - id; vec.push_back(id); if(mp3.find(id) != mp3.end()){ if(mp3[id] != x)flag = false; } else mp3[id] = x; } if((!flag) || (n1 < max(n2,n3)) || (n1 > max(n2,n3)+1)){ printf("Case #%d: IMPOSSIBLE\n",iCase); continue; } vec.push_back(n2-1); vec.push_back(n3-1); sort(vec.begin(),vec.end()); vec.erase(unique(vec.begin(),vec.end()),vec.end()); int mn = max(n2,n3); B.init(); B.mat[0][0] = B.mat[1][1] = 1; B2.init(); B2.mat[0][0] = B2.mat[1][1] = 1; if(vec[0] > 0)B = B * pow_M(A[10*11*11+10*11+10],vec[0]); if(vec[0] > 0)B2 = B2 * pow_M(A2[10*11*11+10*11+10],vec[0]); int sz = vec.size(); for(int i = 0;i < sz;i++){ if(i > 0){ B = B * pow_M(A[10*11*11+10*11+10],vec[i]-vec[i-1]-1); } int x,y,z; if(mp2.find(vec[i]) == mp2.end())x = 10; else x = mp2[vec[i]]; if(vec[i] >= n2)x = 0; if(mp3.find(vec[i]) == mp3.end())y = 10; else y = mp3[vec[i]]; if(vec[i] >= n3)y = 0; if(mp1.find(vec[i]) == mp1.end())z = 10; else z = mp1[vec[i]]; if(vec[i] >= n1)z = 0; if(vec[i] != n2-1 && vec[i] != n3-1){ B = B * A[x*11*11+y*11+z]; B2 = B2 * A2[x*11*11+y*11+z]; } else { C.init(); C2.init(); for(int p = 0;p < 10;p++) for(int q = 0;q < 10;q++) for(int r = 0;r < 10;r++){ if(x != 10 && p != x)continue; if(y != 10 && q != y)continue; if(z != 10 && r != z)continue; if(n2 != 1 && vec[i] == n2-1 && p == 0)continue; if(n3 != 1 && vec[i] == n3-1 && q == 0)continue; if(vec[i] >= n2 && p != 0)continue; if(vec[i] >= n3 && q != 0)continue; if(p+q == r)C.mat[0][0]++; if(p+q == r+10)C.mat[0][1]++; if(p+q+1 == r)C.mat[1][0]++; if(p+q+1 == r + 10)C.mat[1][1]++; if(p+q == r)Add(C2.mat[0][0],1); if(p+q == r+10)Add(C2.mat[0][1],1); if(p+q+1 == r)Add(C2.mat[1][0],1); if(p+q+1 == r + 10)Add(C2.mat[1][1],1); } B = B*C; B2 = B2*C2; } } int ans = 0; int ans2 = 0; if(n1 == max(n2,n3)){ ans = B.mat[0][0]; ans2 = B2.mat[0][0]; } else{ if(mp1.find(n1-1) != mp1.end() && mp1[n1-1] != 1){ printf("Case #%d: IMPOSSIBLE\n",iCase); continue; } ans = B.mat[0][1]; ans2 = B2.mat[0][1]; } if(ans2 == 0)printf("Case #%d: IMPOSSIBLE\n",iCase); else printf("Case #%d: %d\n",iCase,ans); } return 0; }