隐藏
「bzoj3917」「Baltic2014」sequence - 枚举乱搞 | Bill Yang's Blog

路终会有尽头,但视野总能看到更远的地方。

0%

「bzoj3917」「Baltic2014」sequence - 枚举乱搞

题目大意

    序列$A$由从$N$开始的连续$K$个数按顺序构成,现在将$A$中的每个数只保留某一个数码,记为序列$B$,给定$K$和$B$,求可能的最小的$N$。


题目分析

考虑从低位到高位确定每个数。
我们对每个数$a_i$维护一个集合$S_{a_i}$表示$a_i$数位中存在的数。
一开始的时候每个$S_{a_i}$中仅有$b_i$一个元素。
接下来我们枚举当前位$n$的取值,更新所有数的$S$,然后考虑下一位。
这样每次序列的规模以$\frac1{10}$的速度缩减,时间复杂度为:

注意特殊处理$n=2$的情况,当最后两位分别含有$9,0$时可能死递归。
细节较多,本代码暂时可通过目前所有hack数据。
Hack数据


代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<climits>
#include<bitset>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;

typedef long long LL;
#define bit bitset<10>

inline const LL Get_Int() {
LL num=0,bj=1;
char x=getchar();
while(x<'0'||x>'9') {
if(x=='-')bj=-1;
x=getchar();
}
while(x>='0'&&x<='9') {
num=num*10+x-'0';
x=getchar();
}
return num*bj;
}

LL Solve(vector<bit> a,bool zero) {
int down=0,up=9;
if(a.size()==1) {
if(a[0].none()) {
if(zero)return 0;
down=1;
} else {
if(a[0].to_ulong()==1)return 10;
bool flag=0;
LL sum=0;
for(int i=1; i<=9; i++)
if(a[0].test(i)) {
sum=sum*10+i;
if(a[0].test(0)&&!flag)flag=1,sum*=10;
}
return sum;
}
} else if(a.size()==2&&!a[0].test(9)&&!a[1].test(0))up=8;
LL ans=LLONG_MAX/2;
for(int i=down; i<=up; i++) {
vector<bit> New;
bit v;
int now=i;
for(auto x:a) {
if(now==10) {
now=0;
New.push_back(v);
v.reset();
}
x.reset(now++);
v|=x;
}
New.push_back(v);
LL sum=Solve(New,!(i==0&&(a[0].test(0)||!zero)))*10+i;
ans=min(ans,sum);
}
return ans;
}

int n;
vector<bit> a;

int main() {
n=Get_Int();
for(int i=1; i<=n; i++) {
bit tmp;
tmp[Get_Int()]=1;
a.push_back(tmp);
}
LL ans=Solve(a,1);
printf("%lld\n",ans==0?10:ans);
return 0;
}
姥爷们赏瓶冰阔落吧~