1 条题解
-
0
P6740 题解
题目大意
给定 个数码 ,求最小的正整数 使得对于所有 ,数码 在数字串 中出现过。
数据范围:。
代码呈现
考虑推广原问题,设数码集 表示 中必须出现的数码集合。
观察 ,注意到删掉末位后这些数会 个一组地变成相同的数,容易发现可以把这些数压缩到一起,然后把没满足的条件放进新的 里,我们就成功构造了一个规模更小的子问题,枚举末位递归求解即可。
时间复杂度 $T(n)=10\times T(\dfrac n{10})+\mathcal O(n)=\mathcal O(n\log n)$,还有一些细节要注意:
- 特判 的情况,以及 且填的数码形如 的情况。
- 注意判断当前 是否有前导 ,以及这些前导 是否一定要保留。
时间复杂度 。
代码呈现
#include<bits/stdc++.h> #define int long long using namespace std; const int B=1023; inline int b(int x) { return 1<<x; } inline int d(int x,int v) { return (x>>v)&1; } inline int dfs(const vector<int> &lim,int lst,bool rem0) { //required digits, last digit, need remain zero? if(lim.size()==1) { int S=lim[0],res=0; if(S==0) return (!lst&&rem0)?1:0; //need 1 to be the highest digit in order to protect the 0 if(S==1) return 10; //only need zero bool req0=d(S,0); //need 0? for(int i=1;i<=9;++i) if(d(S,i)) { res=res*10+i; if(req0) res=res*10,req0=false; //push 0 after the first non-0 digit } return res; } int res=1e16; for(int s=0;s<=9;++s) { //last digit if(lim.size()==2&&s==9&&lst==9&&!d(lim[0],9)&&!d(lim[1],0)) continue; //no use 9...9,10...0 vector <int> newlim; for(int i=0,t=s,S=0;i<(int)lim.size();++i,t=(t+1)%10) { S|=lim[i]&(1023^b(t)); if(i==(int)lim.size()-1||t==9) newlim.push_back(S),S=0; } res=min(res,dfs(newlim,s,d(lim[0],0))*10+s); } return res; } signed main() { int n; scanf("%lld",&n); vector <int> lim(n); for(int &i:lim) scanf("%lld",&i),i=b(i); printf("%lld\n",dfs(lim,0,1)); return 0; }
- 1
信息
- ID
- 5582
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者