[zoj3596]DP(BFS)
题意:求n的最小倍数,满足性质P:十进制的每一位上的数有m种(0<m<=10)。
思路:直接枚举n的最小倍数,然后检测是否满足性质P,n一大很容易超时,并且无法判断无解的情况。巧妙的做法是一位位构造数,同时保存每种数字的使用情况和对n的余数作为状态,如果一个状态出现过,那么后面再一次出现的时候位数肯定比之前多,故答案没之前优,舍弃。由于取模的性质,转移方程也很好写,具体见代码。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #pragma comment(linker, "/STACK:10240000,10240000") 2 3 #include <iostream> 4 #include <cstdio> 5 #include <algorithm> 6 #include <cstdlib> 7 #include <cstring> 8 #include <map> 9 #include <queue> 10 #include <deque> 11 #include <cmath> 12 #include <vector> 13 #include <ctime> 14 #include <cctype> 15 #include <set> 16 #include <bitset> 17 #include <functional> 18 #include <numeric> 19 #include <stdexcept> 20 #include <utility> 21 22 using namespace std; 23 24 #define mem0(a) memset(a, 0, sizeof(a)) 25 #define mem_1(a) memset(a, -1, sizeof(a)) 26 #define lson l, m, rt << 1 27 #define rson m + 1, r, rt << 1 | 1 28 #define define_m int m = (l + r) >> 1 29 #define rep_up0(a, b) for (int a = 0; a < (b); a++) 30 #define rep_up1(a, b) for (int a = 1; a <= (b); a++) 31 #define rep_down0(a, b) for (int a = b - 1; a >= 0; a--) 32 #define rep_down1(a, b) for (int a = b; a > 0; a--) 33 #define all(a) (a).begin(), (a).end() 34 #define lowbit(x) ((x) & (-(x))) 35 #define constructInt5(name, a, b, c, d, e) name(int a = 0, int b = 0, int c = 0, int d = 0, int e = 0): a(a), b(b), c(c), d(d), e(e) {} 36 #define constructInt4(name, a, b, c, d) name(int a = 0, int b = 0, int c = 0, int d = 0): a(a), b(b), c(c), d(d) {} 37 #define constructInt3(name, a, b, c) name(int a = 0, int b = 0, int c = 0): a(a), b(b), c(c) {} 38 #define constructInt2(name, a, b) name(int a = 0, int b = 0): a(a), b(b) {} 39 #define pchr(a) putchar(a) 40 #define pstr(a) printf("%s", a) 41 #define sstr(a) scanf("%s", a) 42 #define sint(a) scanf("%d", &a) 43 #define sint2(a, b) scanf("%d%d", &a, &b) 44 #define sint3(a, b, c) scanf("%d%d%d", &a, &b, &c) 45 #define pint(a) printf("%d\n", a) 46 #define test_print1(a) cout << "var1 = " << a << endl 47 #define test_print2(a, b) cout << "var1 = " << a << ", var2 = " << b << endl 48 #define test_print3(a, b, c) cout << "var1 = " << a << ", var2 = " << b << ", var3 = " << c << endl 49 #define mp(a, b) make_pair(a, b) 50 #define pb(a) push_back(a) 51 52 typedef long long LL; 53 typedef pair<int, int> pii; 54 typedef vector<int> vi; 55 56 const int dx[8] = {0, 0, -1, 1, 1, 1, -1, -1}; 57 const int dy[8] = {-1, 1, 0, 0, 1, -1, 1, -1 }; 58 const int maxn = 3e4 + 7; 59 const int md = 10007; 60 const int inf = 1e9 + 7; 61 const LL inf_L = 1e18 + 7; 62 const double pi = acos(-1.0); 63 const double eps = 1e-6; 64 65 template<class T>T gcd(T a, T b){return b==0?a:gcd(b,a%b);} 66 template<class T>bool max_update(T &a,const T &b){if(b>a){a = b; return true;}return false;} 67 template<class T>bool min_update(T &a,const T &b){if(b<a){a = b; return true;}return false;} 68 template<class T>T condition(bool f, T a, T b){return f?a:b;} 69 template<class T>void copy_arr(T a[], T b[], int n){rep_up0(i,n)a[i]=b[i];} 70 int make_id(int x, int y, int n) { return x * n + y; } 71 72 const int maxI = 1e8; 73 const int Len = 8; 74 75 struct BigInt { 76 vi num; 77 bool symbol; 78 BigInt() { num.clear(); symbol = 0; } 79 BigInt(int x) { symbol = 0; if (x < 0) { symbol = 1; x = -x; } num.push_back(x % maxI); if (x >= maxI) num.push_back(x / maxI); } 80 BigInt(bool s, vi x) { symbol = s; num = x; } 81 BigInt(char s[]) { 82 int len = strlen(s), x = 1, sum = 0, p = s[0] == '-'; 83 symbol = p; 84 for (int i = len - 1; i >= p; i--) { 85 sum += (s[i] - '0') * x; 86 x *= 10; 87 if (x == 1e8 || i == p) { 88 num.push_back(sum); 89 sum = 0; 90 x = 1; 91 } 92 } 93 while (num.back() == 0 && num.size() > 1) num.pop_back(); 94 } 95 96 void push(int x) { num.push_back(x); } 97 98 BigInt abs() const { return BigInt(false, num); } 99 100 bool smaller(const vi &a, const vi &b) const { 101 if (a.size() != b.size()) return a.size() < b.size(); 102 for (int i = a.size() - 1; i >= 0; i--) { 103 if (a[i] != b[i]) return a[i] < b[i]; 104 } 105 return 0; 106 } 107 108 bool operator < (const BigInt &p) const { 109 if (symbol && !p.symbol) return true; 110 if (!symbol && p.symbol) return false; 111 if (symbol && p.symbol) return smaller(p.num, num); 112 return smaller(num, p.num); 113 } 114 115 bool operator > (const BigInt &p) const { 116 return p < *this; 117 } 118 119 bool operator == (const BigInt &p) const { 120 return !(p < *this) && !(*this < p); 121 } 122 123 bool operator >= (const BigInt &p) const { 124 return !(*this < p); 125 } 126 127 bool operator <= (const BigInt &p) const { 128 return !(p < *this); 129 } 130 131 vi add(const vi &a, const vi &b) const { 132 vi c; 133 c.clear(); 134 int x = 0; 135 for (int i = 0; i < a.size(); i++) { 136 x += a[i]; 137 if (i < b.size()) x += b[i]; 138 c.push_back(x % maxI); 139 x /= maxI; 140 } 141 for (int i = a.size(); i < b.size(); i++) { 142 x += b[i]; 143 c.push_back(x % maxI); 144 x /= maxI; 145 } 146 if (x) c.push_back(x); 147 while (c.back() == 0 && c.size() > 1) c.pop_back(); 148 return c; 149 } 150 151 vi sub(const vi &a, const vi &b) const { 152 vi c; 153 c.clear(); 154 int x = 1; 155 for (int i = 0; i < b.size(); i++) { 156 x += maxI + a[i] - b[i] - 1; 157 c.push_back(x % maxI); 158 x /= maxI; 159 } 160 for (int i = b.size(); i < a.size(); i++) { 161 x += maxI + a[i] - 1; 162 c.push_back(x % maxI); 163 x /= maxI; 164 } 165 while (c.back() == 0 && c.size() > 1) c.pop_back(); 166 return c; 167 } 168 169 vi mul(const vi &a, const vi &b) const { 170 vi c; 171 c.resize(a.size() + b.size()); 172 for (int i = 0; i < a.size(); i++) { 173 for (int j = 0; j < b.size(); j++) { 174 LL tmp = (LL)a[i] * b[j] + c[i + j]; 175 c[i + j + 1] += tmp / maxI; 176 c[i + j] = tmp % maxI; 177 } 178 } 179 while (c.back() == 0 && c.size() > 1) c.pop_back(); 180 return c; 181 } 182 183 vi div(const vi &a, const vi &b) const { 184 vi c(a.size()), x(1, 0), y(1, 0), z(1, 0), t(1, 0); 185 y.push_back(1); 186 for (int i = a.size() - 1; i >= 0; i--) { 187 z[0] = a[i]; 188 x = add(mul(x, y), z); 189 if (smaller(x, b)) continue; 190 int l = 1, r = maxI - 1; 191 while (l < r) { 192 int m = (l + r + 1) >> 1; 193 t[0] = m; 194 if (smaller(x, mul(b, t))) r = m - 1; 195 else l = m; 196 } 197 c[i] = l; 198 t[0] = l; 199 x = sub(x, mul(b, t)); 200 } 201 while (c.back() == 0 && c.size() > 1) c.pop_back(); 202 return c; 203 } 204 205 BigInt operator + (const BigInt &p) const{ 206 if (!symbol && !p.symbol) return BigInt(false, add(num, p.num)); 207 if (!symbol && p.symbol) return *this >= p.abs()? BigInt(false, sub(num, p.num)) : BigInt(true, sub(p.num, num)); 208 if (symbol && !p.symbol) return (*this).abs() > p? BigInt(true, sub(num, p.num)) : BigInt(false, sub(p.num, num)); 209 return BigInt(true, add(num, p.num)); 210 } 211 212 BigInt operator - (const BigInt &p) const { 213 return *this + BigInt(!p.symbol, p.num); 214 } 215 216 BigInt operator * (const BigInt &p) const { 217 BigInt res(symbol ^ p.symbol, mul(num, p.num)); 218 if (res.symbol && res.num.size() == 1 && res.num[0] == 0) res.symbol = false; 219 return res; 220 } 221 222 BigInt operator / (const BigInt &p) const { 223 if (p == BigInt(0)) return p; 224 BigInt res(symbol ^ p.symbol, div(num, p.num)); 225 if (res.symbol && res.num.size() == 1 && res.num[0] == 0) res.symbol = false; 226 return res; 227 } 228 229 BigInt operator % (const BigInt &p) const { 230 return *this - *this / p * p; 231 } 232 233 void show() const { 234 if (symbol) putchar('-'); 235 printf("%d", num[num.size() - 1]); 236 for (int i = num.size() - 2; i >= 0; i--) { 237 printf("%08d", num[i]); 238 } 239 //putchar('\n'); 240 } 241 242 int TotalDigit() const { 243 int x = num[num.size() - 1] / 10, t = 1; 244 while (x) { 245 x /= 10; 246 t++; 247 } 248 return t + (num.size() - 1) * Len; 249 } 250 251 }; 252 typedef BigInt bi; 253 254 struct Node { 255 int used, rest, cnt, fa, val; 256 constructInt5(Node, used, rest, cnt, fa, val); 257 } que[3000000]; 258 bool mark[1 << 10][1000]; 259 int n, m; 260 261 bi get(int pos) { 262 if (pos == 0) return 0; 263 return get(que[pos].fa) * 10 + que[pos].val; 264 } 265 266 void bfs() { 267 mem0(mark); 268 int head = 0, tail = 0; 269 que[tail ++] = Node(0, 0, 0, 0, 0); 270 Node hnode; 271 while (head < tail) { 272 hnode = que[head ++]; 273 if (hnode.cnt > m) continue; 274 if (hnode.cnt == m && hnode.rest == 0) break; 275 rep_up0(i, 10) { 276 if (hnode.cnt == 0 && i == 0) continue; 277 if (hnode.used & (1 << i)) { 278 Node newn = Node(hnode.used, (hnode.rest * 10 + i) % n, hnode.cnt, head - 1, i); 279 if (mark[newn.used][newn.rest]) continue; 280 mark[newn.used][newn.rest] = true; 281 que[tail ++] = newn; 282 } 283 else { 284 Node newn = Node(hnode.used | (1 << i), (hnode.rest * 10 + i) % n, hnode.cnt + 1, head - 1, i); 285 if (mark[newn.used][newn.rest]) continue; 286 mark[newn.used][newn.rest] = true; 287 que[tail ++] = newn; 288 } 289 } 290 } 291 if (hnode.cnt != m || hnode.rest != 0) { 292 puts("Impossible"); 293 return ; 294 } 295 bi ans = get(head - 1); 296 ans.show(); 297 printf("=%d*", n); 298 (ans / n).show(); 299 pchr('\n'); 300 } 301 302 int main() { 303 //freopen("in.txt", "r", stdin); 304 int T; 305 cin >> T; 306 while (T --) { 307 cin >> n >> m; 308 bfs(); 309 } 310 return 0; 311 }