[zoj3596]DP(BFS)

题意:求n的最小倍数,满足性质P:十进制的每一位上的数有m种(0<m<=10)。

思路:直接枚举n的最小倍数,然后检测是否满足性质P,n一大很容易超时,并且无法判断无解的情况。巧妙的做法是一位位构造数,同时保存每种数字的使用情况和对n的余数作为状态,如果一个状态出现过,那么后面再一次出现的时候位数肯定比之前多,故答案没之前优,舍弃。由于取模的性质,转移方程也很好写,具体见代码。

  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
", 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('
');
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('
');
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 }
View Code
原文地址:https://www.cnblogs.com/jklongint/p/4480793.html