#include #include #include #include typedef uint32_t DWORD; typedef uint64_t QWORD; #define MOD_BASE 1000000007 typedef struct _bitvec_ { DWORD bits[2049]; DWORD cnt; } BITVEC, *PBITVEC; BITVEC bitvecs[20]; DWORD max[65536]; DWORD twohat[17] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536}; DWORD masks[32] = { 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x00000080, 0x00000100, 0x00000200, 0x00000400, 0x00000800, 0x00001000, 0x00002000, 0x00004000, 0x00008000, 0x00010000, 0x00020000, 0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000, 0x00800000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, }; void init(PBITVEC pbv, int n) { int i; DWORD *p = &(pbv->bits[0]); for(i = 0; i < n; i++) { *p++ = 0; } pbv->cnt = 0; } void SetCnt(PBITVEC pbv, int n) { DWORD mask; int index; if((n >= 1) && (n <= 65536)) { n--; index = n >> 5; mask = masks[n & 0x1f]; if((pbv->bits[index] & mask) == 0) { pbv->bits[index] |= mask; pbv->cnt++; } } } int Intersect(PBITVEC pbv1, PBITVEC pbv2, DWORD cnt) { DWORD *p1, *p2; DWORD i; p1 = &(pbv1->bits[0]); p2 = &(pbv2->bits[0]); for(i = 0; i < cnt ; i++, p1++, p2++) { if((*p1 & *p2) != 0) { return 1; } } return 0; } int CheckUnion(PBITVEC pbv1, PBITVEC pbv2, int n) { DWORD *p1, *p2; DWORD i, cnt, rem; p1 = &(pbv1->bits[0]); p2 = &(pbv2->bits[0]); cnt = (n >> 5); rem = n & 0x1f; for(i = 0; i < cnt ; i++, p1++, p2++) { if((*p1 | *p2) != 0xffffffff) { return -1; } } if(rem > 0) { rem = (1 << (rem)) - 1; if((*p1 | *p2) != rem) { return -2; } } return 0; } int Compare(int start1, int start2, int cnt) { int i; DWORD *p1, *p2; for(i = 0, p1 = &(max[start1]), p2 = &(max[start2]) ; i < cnt ; i++, p1++, p2++) { if(*p1 != *p2) { return -1; } } return 0; } DWORD ChkSolve(DWORD start, DWORD cnt, int nvals, int level) { DWORD cntr, swtch, *p, icnt; DWORD ret = 0; QWORD tval; PBITVEC pbv1, pbv2; pbv1 = &bitvecs[0]; pbv2 = &bitvecs[1]; icnt = (nvals >> 5) + 1; init(pbv1, icnt); init(pbv2, icnt); p = &(max[start]); swtch = cnt/2; for(cntr = 0; cntr < cnt; cntr++, p++) { if(cntr < swtch) { SetCnt(pbv1, *p); } else { SetCnt(pbv2, *p); } } if(Intersect(pbv1, pbv2, icnt) != 0) { // if value occurs in top and bottom, all must have high bti on or all of // and values at i and i + two_m2 + i must be the same if(Compare(start, start + (cnt+1)/2, cnt/2) != 0) { return 0; // not the same no solution } else { if(pbv2->cnt == 1) { // all are the same 2^level possibilities return twohat[level]; } else { // we only need to check the bottom // any solution with all 2^level bits onis also a solution with the same bit off tval = ChkSolve(start + cnt/2, (cnt+1)/2, nvals, level - 1); return (DWORD)((2*tval) % MOD_BASE); } } } else if(pbv1->cnt == 1) { // only one value in top check the bottom // bits below can take any value tval = twohat[level - 1]; if(pbv2->cnt == 1) { tval *= twohat[level-1]; return (DWORD)(tval % MOD_BASE); } else { tval *= ChkSolve(start + cnt/2, (cnt+1)/2, nvals, level - 1); return (DWORD)(tval % MOD_BASE); } } else if(pbv2->cnt == 1) { // only one value in bottom check the top // bits below can take any value tval = twohat[level - 1]; tval *= ChkSolve(start, cnt/2, nvals, level - 1); return (DWORD)(tval % MOD_BASE); } else { if((tval = ChkSolve(start, cnt/2, nvals, level - 1)) != 0) { tval *= ChkSolve(start + cnt/2, (cnt+1)/2, nvals, level - 1); return (DWORD)(tval % MOD_BASE); } else { return 0; } } } int main() { int m, n, i; DWORD ind, two_m, two_m2, cnt, ret; QWORD tval; PBITVEC pbv1, pbv2; if(scanf("%d %d", &m, &n) != 2) { return -1; } if((m < 0) || (m > 16) || (n < 1) || (n > (int)twohat[m])) { return -2; } if(m == 0) { printf("1\n"); return 0; } pbv1 = &bitvecs[0]; pbv2 = &bitvecs[1]; two_m = twohat[m]; two_m2 = twohat[m-1]; cnt = (n >> 5) + 1; init(pbv1, cnt); init(pbv2, cnt); for(ind = 0; ind < two_m ; ind++) { if(scanf("%d", &i) != 1){ return -3; } max[ind] = i; if(ind < two_m2) { SetCnt(pbv1, i); } else { SetCnt(pbv2, i); } } if(CheckUnion(pbv1, pbv2, n) != 0) { // not all values appear ret = 0; } else if(Intersect(pbv1, pbv2, cnt) != 0) { // if value occurs in top and bottom, all must have high bit on or all off // and values at i and i + two_m2 + i must be the same if(Compare(0, two_m2, two_m2) != 0) { ret = 0; } else { if(pbv2->cnt == 1) { // all the same, 2^m possibilities ret = twohat[m]; } else { // we only need to check the bottom tval = ChkSolve(two_m2, two_m2, n, m-1); ret = (DWORD)((2*tval) % MOD_BASE); } } } else if(pbv1->cnt == 1) { // only one value in top check the bottom // 2^(m-1) choices tval = twohat[m-1]; if(pbv2->cnt == 1) { tval *= twohat[m-1]; ret = (DWORD)(tval % MOD_BASE); } else { tval *= ChkSolve(two_m2, two_m2, n, m-1); ret = (DWORD)(tval % MOD_BASE); } } else if(pbv2->cnt == 1) { // only one value in bottom check the top // 2^(m-1) choices tval = twohat[m-1]; tval *= ChkSolve(0, two_m2, n, m-1); ret = (DWORD)(tval % MOD_BASE); } else { if((tval = ChkSolve(0, two_m2, n, m-1)) != 0) { tval *= ChkSolve(two_m2, two_m2, n, m-1); ret = (DWORD)(tval % MOD_BASE); } else { ret = 0; } } printf("%lu\n", ret); return 0; }