TLE方法:
依次找出丑数,从最小的丑数开始用K个素数来扩增,如果这些扩曾出的数字P,没有被加入队列,那么就加入队列。 扩增完后,当前最小丑数出队。 从下一个丑数开始扩增……
我用了SPLAY,我把队列大小限制在50W以内……然后第N个出队的才是正确答案。 40W都不行…… 如果不限制队列大小,貌似计算太慢太慢…… 只能过11个测试点。
Compiling... Compile: OK Executing... Test 1: TEST OK [0.003 secs, 3504 KB] Test 2: TEST OK [0.003 secs, 3504 KB] Test 3: TEST OK [0.005 secs, 3504 KB] Test 4: TEST OK [0.032 secs, 3636 KB] Test 5: TEST OK [0.049 secs, 3768 KB] Test 6: TEST OK [0.211 secs, 4692 KB] Test 7: TEST OK [0.084 secs, 4032 KB] Test 8: TEST OK [0.062 secs, 3900 KB] Test 9: TEST OK [0.003 secs, 3504 KB] Test 10: TEST OK [0.003 secs, 3504 KB] Test 11: TEST OK [0.003 secs, 3504 KB]
> Run 12: Execution error: |
/* TASK:humble LANG:C++ */ #include <cstdio> int k, n; int a[102]; void init() { scanf("%d%d", &k, &n); for (int i = 0; i != k; ++ i) scanf("%d", &a[i]); } struct node { node *c[2]; int key, size; node() { key = size = 0; c[0] = c[1] = this; } node(int KEY_, node *c0, node *c1) { key = KEY_; c[0] = c0; c[1] = c1; } node* rz(){return size = c[0] -> size + c[1] -> size + 1, this;} }Tnull, *null = &Tnull; const int maxint = 0x7fffffff; struct splay { node *root; splay() { root = (new node(*null)) -> rz(); root -> key = maxint; } void zig(bool d) { node *t = root -> c[d]; root -> c[d] = null -> c[d]; null -> c[d] = root; root = t; } void zigzig(bool d) { node *t = root -> c[d] -> c[d]; root -> c[d] -> c[d] = null -> c[d]; null -> c[d] = root -> c[d]; root -> c[d] = null -> c[d] -> c[!d]; null -> c[d] -> c[!d] = root -> rz(); root = t; } void finish(bool d) { node *t = null -> c[d], *p = root -> c[!d]; while (t != null) { t = null -> c[d] -> c[d]; null -> c[d] -> c[d] = p; p = null -> c[d] -> rz(); null -> c[d] = t; } root -> c[!d] = p; } void select(int k)//谁有k个儿子 { int t; while (1) { bool d = k > (t = root -> c[0] -> size); if (k == t || root -> c[d] == null) break; if (d) k -= t + 1; bool dd = k > (t = root -> c[d] -> c[0] -> size); if (k == t || root -> c[d] -> c[dd] == null) {zig(d);break;} if (dd) k -= t + 1; d != dd ? zig(d), zig(dd) : zigzig(d); } finish(0), finish(1); root -> rz(); } void search(int x) { while (1) { bool d = x > root -> key; if (root -> c[d] == null) break; bool dd = x > root -> c[d] -> key; if (root -> c[d] -> c[dd] == null) {zig(d); break;} d != dd ? zig(d), zig(dd) : zigzig(d); } finish(0), finish(1); root -> rz(); if (x > root -> key) select(root -> c[0] -> size + 1); } void ins(int x) { search(x); node *oldroot = root; root = new node(x, oldroot -> c[0], oldroot); oldroot -> c[0] = null; oldroot -> rz(); root -> rz(); } void del(int x) { search(x); node *oldroot = root; root = root -> c[1]; select(0); root -> c[0] = oldroot -> c[0]; root -> rz(); delete oldroot; } int sel(int k){return select(k - 1), root -> key;} int ran(int x){return search(x), root -> c[0] -> size + 1;} }sp; void doit() { sp.ins(1); int count = -1; while (1) { int now = sp.sel(1); ++ count; if (count == n) { printf("%d\n",now); return; } if (sp.root -> size >= 2000000) continue; for (int i = 0; i != k; ++ i) { long long tmp = (long long)now * a[i]; if (tmp > 2000000000) continue; sp.search(tmp); int p = sp.root -> key; if (sp.root->key == tmp) continue; else sp.ins(tmp); } now = sp.sel(1); sp.del(now); } } int main() { freopen("humble.in","r",stdin); freopen("humble.out","w",stdout); init(); doit(); return 0; }
正确方法:
思路: 假如已经有P个丑数,那么我可以把这P个丑数,分别和K个已知素数进行相乘,得到的最小的(同时不能是已经得到的丑数),就是第P+1个丑数。
这其中有一个搜索优化。
第i个素数, 假如和第j个丑数,产生了最小的,也就是第p+1个丑数。 那么这第i个素数,以后如果要产生第X个丑数,他一定从第j个丑数之后搜索。【有点拗口】
细节: 从丑数5,可以产生5*2 = 10. 从丑数2, 可以产生2*5 = 10. 所以在进行产生丑数运算前,要先保证,所有的第i个素数,和他们“当前搜索丑是数j” ,保证素数i * 丑数j > 第P个丑数。
Executing... Test 1: TEST OK [0.003 secs, 3756 KB] Test 2: TEST OK [0.003 secs, 3756 KB] Test 3: TEST OK [0.003 secs, 3756 KB] Test 4: TEST OK [0.005 secs, 3756 KB] Test 5: TEST OK [0.008 secs, 3756 KB] Test 6: TEST OK [0.022 secs, 3756 KB] Test 7: TEST OK [0.005 secs, 3756 KB] Test 8: TEST OK [0.005 secs, 3756 KB] Test 9: TEST OK [0.003 secs, 3756 KB] Test 10: TEST OK [0.003 secs, 3756 KB] Test 11: TEST OK [0.003 secs, 3756 KB] Test 12: TEST OK [0.081 secs, 3756 KB] All tests OK.
/* TASK:humble LANG:C++ */ #include <cstdio> int k, n; int a[102], w[102]={0}, x[100005] = {1}; int main() { freopen("humble.in","r",stdin); freopen("humble.out","w",stdout); scanf("%d%d", &k, &n); for (int i = 0; i != k; ++ i) scanf("%d", &a[i]); for (int j = 1; j <= n; ++ j) { int tmp = 0x7fffffff, wz; for (int i = 0; i != k; ++ i) while (x[w[i]] * a[i] <= x[j - 1]) ++ w[i]; for (int i = 0; i != k; ++ i) { if (x[w[i]] * a[i] < tmp) { tmp = x[w[i]] * a[i]; wz = i; } } ++ w[wz]; x[j] = tmp; } printf("%d\n", x[n]); return 0; }