CCPC2026 黑龙江省大学生程序设计竞赛
CCPC2026 黑龙江省大学生程序设计竞赛
F.复读机
签到题
G.卡卡数
统计 \([0,10^x-1]\) 中所有整数写成十进制后,数字 \(1\) 出现的总次数,对
998244353取模。
签到题*2,答案为 \(x\sdot10^{\max(x-1,0)}\mod 998244353\).
H.周二会员日
给定 \(x\),求 \(4x-3\),读入形如 \(a.bb\) 的字符串,数据范围 \((2<x\le4\times 10^{16})\),答案精确到小数点后两位.
为了防止 long double 爆精度,采用类似于高精度的写法,将 \(x\) 扩大100倍后对字符串操作,实际上直接转成 unsigned long long 计算最后转回字符串即可。
#include<bits/stdc++.h>
#define int unsigned long long
using namespace std;
void sol(){
string s;
cin>>s;
vector<int> num;
for(auto ch:s){
if(ch=='.') continue;
num.push_back(ch-'0');
}
int sum(0);
for(int i=0;i<(int)num.size();++i){
sum+=num[i];
if(i!=(int)num.size()-1) sum*=10ull;
}
int ans(sum*4-300);
string answ("");
int cnt(0);
for(;ans;ans/=10){
if(cnt==2) answ+='.';
cnt++;
answ+=(char)('0'+ans%10);
}
reverse(answ.begin(),answ.end());
cout<<answ<<endl;
}
signed main(){
int T(1);
cin>>T;
while(T--) sol();
}
M.六个核桃
给定 \(m\),构造排列 \(p\),最大化 \(\sum \min(|p_i-i|,m)\).
不妨直接考虑没有 \(m\) 的情况,为了让贡献最大,最简单的构造方法可以是倒序构造,此时的最大值即为 \(\lfloor \frac{n^2}{2} \rfloor\),再有了 \(m\) 的限制以后,我们当然希望构造出的差值尽量稳定,因此与倒序构造类似的可以采用平移构造,将原来的顺序序列向右平移轮换,注意到当平移轮换 \(\lfloor \frac{n}{2} \rfloor\) 次以后答案最大,因此对于每个 \(m\),考虑采用不同的平移策略。首先将顺序序列右平移轮换 \(m\) 位得到 \(n-m\) 个贡献为 \(m\) 的位置,此时前 \(m\) 位贡献均为 \(n-m\),因此自然启示比较 \(m\) 与 \(n-m\) 的大小。对 \(m\) 分类讨论。
- 当 \(n-m\ge m\) 时,此时最大值为全部位均取上界 \(m\),直接服用之前的轮换构造即可。
- 当 \(n-m<m\) 时,对原来构造调整,首先后 \(n-m\) 位贡献恰好卡到上界 \(m\),则考虑前 \(n-m\) 位,为了让贡献卡到上界的位置尽量多,因此对前 \(n-m\) 位的每一位 \(i\) 构造 \(p_i=i+m\),直到 \(i=n-m\)。现在还剩下 \(n-m\) 到 \(m\) 位置,直接采用局部的倒序构造或者平移轮换一半构造即可。
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,m;
cin>>n>>m;
vector<int> a(n+10);
if((m<<1)<=n){
for(int i=m+1;i<=n;++i) a[i]=i-m;
for(int i=1;i<=m;++i) a[i]=i+n-m;
for(int i=1;i<=n;++i) cout<<a[i]<<' ';
}else{
for(int i=m+1;i<=n;++i) a[i]=i-m;
for(int i=1;i<=n-m;++i) a[i]=i+m;
for(int i=n-m+1;i<=m;++i) a[i]=n+1-i;
for(int i=1;i<=n;++i) cout<<a[i]<<' ';
}
}
C.圆桌会议
构造 \(1\) 到 \(n\) 环形排列,是每个连续三人组的中位数种类尽量少。
感觉很难用语言描述清楚,首先为了得到最优答案,很容易可以想到"中-低-中-高-中"这种构造(或者反过来)可以使中间的三位中位数相同。因此直接就能想到对于 \(n=6\) 时有 456123,此时的中位数种类为4,观察一下,因为首尾的"中-低-中-高-中"构造被破坏了,所以产生了两个多余贡献。为了维护这个结构不被破坏,就需要尾位高于首位,从而完成衔接,因此原来的紧密放置不合理,需要插空放置。
如何考虑插空策略?显然还是以每三个位置为一组,逐渐升高即可。实际上画图还是可以理解的,语言描述颇为抽象。。。

接下来只要对 n%3 分类讨论即可,注意只有当 n%3==1 时才需要特殊处理,也就是最后一个数为了不破坏先前的所有结构,就需要放在最后一组的中位数之下,第一组的中位数之上,然后将先前所有比最后一个数大的数向上平移一位(加一)即可。
#include<bits/stdc++.h>
using namespace std;
void sol(){
int n,res,g;
cin>>n;
vector<int> a(n+10);
res=n%3,g=n/3;
if(!res){
for(int i=1;i<=g;++i)
for(int j=0;j<3;++j)
cout<<i+g*j<<' ';
}else if(res==2){
g++;
for(int i=1;i<g;++i)
for(int j=0;j<3;++j)
cout<<i+g*j<<' ';
cout<<g<<' '<<2*g<<' ';
}else{
for(int i=1;i<=g;++i){
for(int j=0;j<3;++j){
int fac(i+g*j);
cout<<fac+(fac>1+g)<<' ';
}
}
cout<<2+g<<' ';
}
cout<<'\n';
}
int main(){
int T(1);
cin>>T;
while(T--) sol();
}
B.最大数码 2
给定区间 \([l,r]\),求 \(f(x)\) 的最大值,并在达到最大值的 \(x\) 中输出十进制字符串字典序最小者。其中 \(f(x)\) 表示正整数 \(x\) 十进制下表示的最大数码。
称长度为 \(x\) 的字符串 \(P\) 的字典序小于长度为 \(y\) 的字符串 \(Q\),若:\(x<y\) 且对于所有 \(1≤i≤x\) 有 \(p_i=q_i\),或者存在一个整数 \(1≤t≤\min(x,y)\),对于所有 \(1≤i<t\) 有 \(p_i=q_i\),且 \(p_t<q_t\)。
关键在于字典序的定义有些不同,因此字典序和数值大小没有关系。比如 10009 的字典序要比 1009 更小,因此尽可能地让 \(1000...\) 填充更高位更优。
同时注意到当区间长度大于 \(10\) 时,必有 \(f(x)=9\),自然启示对区间长度分类讨论。
- 当区间长度小于 \(10\) 时,直接暴力枚举即可。
- 当区间长度大于等于 \(10\) 时,为了尽可能地让 \(1000...\) 填充更高位,不妨先在区间内寻找最大的
1000...009,必然最优。如果不存在1000...009,意味着区间长度不跨越不同位数,此时直接在 \(l\) 的基础上构造即可。
#include<bits/stdc++.h>
using namespace std;
#define int long long
void sol(){
int l,r;
cin>>l>>r;
if(r-l<10){
auto cmp=[&](string a,string b){
int sia(a.size()),sib(b.size());
int siz(max(sia,sib));
int d(abs(sia-sib));
if(sia>sib){
for(int i=0;i<d;++i) b+='0';
}else{
for(int i=0;i<d;++i) a+='0';
}
for(int i=0;i<siz;++i){
int na(a[i]-'0'),nb(b[i]-'0');
if(na<nb) return true;
else if(na>nb) return false;
else continue;
}
return sib>sia;
};
auto f=[&](int x){
int ans(0);
for(;x;x/=10) ans=max(ans,x%10);
return ans;
};
string anss("999999999");
int ans(0);
for(int i=l;i<=r;++i) ans=max(ans,f(i));
for(int i=l;i<=r;++i){
string s("");
int num=i;
for(;num;num/=10){
int dig=num%10;
s+=(char)(dig+'0');
}
reverse(s.begin(),s.end());
bool flag(0);
for(auto digi:s){
if(digi-'0'==ans){flag=1;break;}
}
if(flag&&cmp(s,anss)) anss=s;
}
cout<<ans<<' '<<anss<<'\n';
}else{
int sta(0);
for(int i=1;;i*=10){
if(i==1) sta=9;
else sta=i+9;
if(i*10+9>r) break;
}
if(sta>=l) cout<<9<<' '<<sta<<'\n';
else{
bool flag(0);
for(int num(l);num;num/=10){
int dig=num%10;
if(dig==9){flag=1;break;}
}
if(flag) cout<<9<<' '<<l<<'\n';
else cout<<9<<' '<<l/10*10+9<<'\n';
}
}
}
signed main(){
int T(1);
cin>>T;
while(T--) sol();
}
J.秋水横渡
有 \(n\) 座周期性开闭关口,关口会在"开启"和"关闭"两种状态之间交替切换,每次维持某一状态的时间均为 \(k\) 个单位时间(即一个完整的开闭周期长度为 \(2k\)),每座关口相位可预设为 \(S_i\),当关口处于开启状态时,竹筏可以瞬间渡过(不花费时间);当关口处于关闭状态时,竹筏必须在关口前等待,直到关口切换为开启状态方可通行。存在全局随机偏移量 \(\Delta\in(0,2k)\) 使得各门相位延迟。已知竹筏会采取最完美的策略来设定所有的 \(S_i\) 以最小化行程耗时,同时每个门之间耗时给定为 \(t_i\)。求最小期望总耗时。
诈骗题。实际上先考虑没有 \(\Delta\) 的情况,此时将 \(S_i\) 设置为某个恰好开门的时段往前回溯 \(pre_i\) 这个相位,可以使得竹筏在通过首门以后一路畅通无阻,即每次到达门都刚好迎来门的”初开“相位。
现在考虑加上 \(\Delta\),由于 \(\Delta\in(0,2k)\),当 \(\Delta\in(0,k)\) 时,此时相当于没有在第一道门等待,因此其后的所有门相位从”初开“加上 \(\Delta\) 后仍然处于开门状态。当 \(\Delta\in(k,2k)\) 时,此时需要在第一道门等待至开门,总偏移量(在第一道门等待的时间加 \(\Delta\))恰好可以使其后的所有门继续满足没有 \(\Delta\) 的”一路畅通“状态。
因此唯一要考虑的即为在第一道门等待时间的期望,因变量为 \(\Delta\),自变量为等待时间,很容易积分出期望为 \(\frac{k}{4}\).
因此答案即为 \(\sum_i t_i+\frac{k}{4}\)。
E.乐乐的杏花
树上点动态开关,当前位置沿边移动,每个时刻查询离当前位置最近的盛开杏花距离。
很基础的树链剖分加线段树维护,维护所有点到当前根节点的距离,取全局最小即可。(太久没写树剖LCA都写瓜了)
#include<bits/stdc++.h>
// #define int long long
#define inf 1e6+10
using namespace std;
const int N=1e5+10;
int n,m,rt(1);
int to[N<<1],head[N],nxt[N<<1];
int fa[N],dep[N],siz[N],dfn[N],rev[N],top[N],son[N];
void add(int u,int v){
to[++to[0]]=v,nxt[to[0]]=head[u],head[u]=to[0];
to[++to[0]]=u,nxt[to[0]]=head[v],head[v]=to[0];
}
void dfs1(int u,int f){
dep[u]=dep[fa[u]=f]+(siz[u]=1);
for(int i=head[u];i;i=nxt[i]){
if(to[i]==f) continue;
dfs1(to[i],u);
siz[u]+=siz[to[i]];
if(siz[to[i]]>=siz[son[u]]) son[u]=to[i];
}
}
void dfs2(int u,int tp){
top[rev[dfn[u]=++dfn[0]]=u]=tp;
if(son[u]) dfs2(son[u],tp);
for(int i=head[u];i;i=nxt[i]){
if(to[i]^fa[u]&&to[i]^son[u]){
dfs2(to[i],to[i]);
}
}
}
int LCA(int x,int y){
for(;top[x]^top[y];){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
x=fa[top[x]];
}
return dep[x]<dep[y]?x:y;
}
namespace TREE{
#define lson pos<<1
#define rson pos<<1|1
struct Node{
int dat,tag;
}t[N<<2];
void push_up(int pos){
t[pos].dat=min(t[lson].dat,t[rson].dat);
}
void add_tag(int pos,int v){
t[pos].tag+=v;
t[pos].dat+=v;
}
void push_down(int pos){
if(!t[pos].tag) return;
add_tag(lson,t[pos].tag);
add_tag(rson,t[pos].tag);
t[pos].tag=0;
}
void build(int pos,int l,int r){
if(l==r) return t[pos].dat=inf,void();
int mid((l+r)>>1);
build(lson,l,mid);
build(rson,mid+1,r);
push_up(pos);
}
void mdy(int pos,int l,int r,int x,int v){
if(l==r) return t[pos].dat=v,t[pos].tag=0,void();
push_down(pos);
int mid((l+r)>>1);
if(x<=mid) mdy(lson,l,mid,x,v);
else mdy(rson,mid+1,r,x,v);
push_up(pos);
}
void modify(int pos,int l,int r,int ql,int qr,int v){
if(ql<=l&&r<=qr) return add_tag(pos,v);
push_down(pos);
int mid((l+r)>>1);
if(ql<=mid) modify(lson,l,mid,ql,qr,v);
if(mid<qr) modify(rson,mid+1,r,ql,qr,v);
push_up(pos);
}
}
bool sta[N];
signed main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n>>m;
for(int i=1;i<n;++i){
int u,v;
cin>>u>>v;
add(u,v);
}
dfs1(1,0);
dfs2(1,1);
for(int i=1;i<=n;++i) dep[i]--;
TREE::build(1,1,n);
while(m--){
int opt,x;
cin>>opt>>x;
if(opt==1){
if(sta[x]){
TREE::mdy(1,1,n,dfn[x],inf);
}else{
int d;
if(dfn[rt]<=dfn[x]&&dfn[x]<=dfn[rt]+siz[rt]-1){
d=abs(dep[rt]-dep[x]);
}else if(dfn[x]<=dfn[rt]&&dfn[rt]<=dfn[x]+siz[x]-1){
d=abs(dep[rt]-dep[x]);
}else{
int lca=LCA(x,rt);
d=dep[rt]+dep[x]-2*dep[lca];
}
TREE::mdy(1,1,n,dfn[x],d);
}
sta[x]^=1;
int ans(TREE::t[1].dat);
if(ans>=N) cout<<2147483648<<'\n';
else cout<<TREE::t[1].dat<<'\n';
}else{
if(dep[rt]>=dep[x]){
TREE::modify(1,1,n,1,n,-1);
TREE::modify(1,1,n,dfn[rt],dfn[rt]+siz[rt]-1,2);
}else{
TREE::modify(1,1,n,1,n,1);
TREE::modify(1,1,n,dfn[x],dfn[x]+siz[x]-1,-2);
}
rt=x;
int ans(TREE::t[1].dat);
if(ans>=N) cout<<2147483648<<'\n';
else cout<<TREE::t[1].dat<<'\n';
}
}
}
A.卡卡杀
树上有不超过 3000 个节点和 3000 名玩家。玩家按最短路逐时刻移动;同点玩家按阵营和冷却规则互相击杀,最后输出存活玩家.
题面太长了,总体来说是一个中模拟,模拟每个时刻的时间并对每个点更新状态,总体时间复杂 \(\Theta(n^2)\)。具体而言,首先需要处理出每个玩家的路径点集:预处理深度和父亲节点数组,然后找起终点 LCA(s,t),向最近公共祖先跳 fa[x] 即可,因为复杂度瓶颈不在求 \(\text{LCA}\),因此直接暴跳即可
。接下来就是按照题目中的要求顺序处理每个事件发生的事件,有一些细节要注意:
- 每次更新对所有节点开桶维护当前节点玩家集合,优先处理当前获胜玩家,他们不需要计入当前节点玩家集合列表。
- 处理“卡卡”以外所有玩家状态,跟据当前时间戳分类四种玩家“击杀贡献”,注意“鹅”玩家杀死“卡卡”后“卡卡”击杀贡献直接置零。同时计数“中立”玩家击杀贡献数,若中立击杀贡献至少为 \(2\),意味着中立玩家之间必然无人生还;若中立击杀贡献为 \(1\),意味着只有一名中立玩家出刀,则当前出刀中立玩家不受伤害。
- 处理“卡卡”伤害,若“卡卡”击杀贡献仍存在,则击杀其他存活玩家。
最后统计所有获胜玩家即可。
#include<bits/stdc++.h>
using namespace std;
const int N=3010;
int n,m;
int to[N<<1],head[N],nxt[N<<1];
int fa[N],dep[N];
vector<int> G[N];
void add(int u,int v){
to[++to[0]]=v,nxt[to[0]]=head[u],head[u]=to[0];
to[++to[0]]=u,nxt[to[0]]=head[v],head[v]=to[0];
}
void dfs(int u,int f){
dep[u]=dep[fa[u]=f]+1;
for(int i=head[u];i;i=nxt[i]){
if(to[i]==f) continue;
dfs(to[i],u);
}
}
int LCA(int x,int y){
vector<int> p;
for(;x^y;){
if(dep[fa[x]]<dep[fa[y]]) swap(x,y);
x=fa[x];
}
return dep[x]<dep[y]?x:y;
}
struct gamer{
int op,tim,s,t,pos;
vector<int> p;
bool w,d;
}a[N];
bool upd(int T){
vector<vector<int>> G(n+10);
bool done(1);
for(int i=1;i<=m;++i){
if(a[i].w||a[i].d) continue;
done=0;
a[i].pos++;
if(a[i].pos==(int)a[i].p.size()-1){
a[i].w=1;
continue;
}
G[a[i].p[a[i].pos]].push_back(i);
}
if(done) return 1;
bool g[5];
for(int u=1;u<=n;++u){
g[1]=g[2]=g[3]=g[4]=0;
int cnt_m(0);
for(auto v:G[u]){
if(!(T%a[v].tim)){
cnt_m+=(a[v].op==4);
g[a[v].op]|=1;
}
}
for(auto v:G[u]){
if(a[v].op==1){
a[v].d|=g[2];
if(a[v].d) g[1]=0;
}
if(a[v].op==2) a[v].d|=(g[3]|g[4]);
if(a[v].op==3) a[v].d|=g[4];
if(a[v].op==4){
if(cnt_m>=2) a[v].d=1;
else if(cnt_m==1&&T%a[v].tim) a[v].d=1;
}
}
for(auto v:G[u]){
if(a[v].d) continue;
if(a[v].op!=1) a[v].d|=g[1];
}
}
return done;
}
int main(){
cin>>n>>m;
for(int i=1;i<n;++i){
int u,v;cin>>u>>v;
add(u,v);
}
dfs(1,0);
for(int i=1;i<=m;++i){
int op,tim,s,t;
vector<int> p;
cin>>op>>tim>>s>>t;
a[i]={op,tim,s,t,0,p,0,0};
int lca(LCA(s,t));
int x(s),y(t);
vector<int> p2;
for(;dep[x]>=dep[lca];x=fa[x]) a[i].p.push_back(x);
for(;dep[fa[y]]>=dep[lca];y=fa[y]) p2.push_back(y);
reverse(p2.begin(),p2.end());
for(auto val:p2) a[i].p.push_back(val);
}
for(int T(1);;T++){
if(upd(T)) break;
}
int sum(0);
for(int i=1;i<=m;++i) sum+=a[i].w;
cout<<sum<<'\n';
for(int i=1;i<=m;++i)
if(a[i].w) cout<<i<<'\n';
}
L.猪猪车
交互猜四位数。一次询问返回位置和数码完全相同的位数,要求 \(12\) 次询问内猜出答案。
学到了 \(\text{minimax}\) 搜索,首先,为了缩小待选择集合,可以先用最多 \(9\) 次询问 \(0000\cdots8888\) 得到答案的构成集合,自然可以得到答案的不同分类 abcd aabc aabb aaab,由不同分类可以将正确答案集合映射为这四种统一构造。接下来为了在 \(3\) 次询问内得到正确答案,需要寻找最优的策略,使得每一次询问都能将当前可能的答案最均匀分割,即利用 \(\text{minimax}\) 搜索。
因为总共的可能性并不太多,因此我们可以将最后三次的决策树暴力搜出来,然后离线查表即可,因此如何制表是关键。我们对当前节点分别记录个内容:当前节点的编号,当前节点的儿子节点编号,当前节点的可能答案集合,显然当可能答案集合只有一个可能答案时(即叶子节点)就是我们要输出的值。那么在向下递归时,需要划分当前答案集合,显然需要利用题目中的“相等个数”也就是每一次机器反馈的值划分,为了实现之前的最优划分,我们需要找到一个问题,使得当前节点下询问这个问题后,最小化儿子节点的可能答案集合大小最大值,也就是尽量让这个问题效率最高。同样的,因为样本数量几乎为常数级别,直接暴力寻找即可。
然后在在线的讯问中,利用之前离线生成的表,按照每次的机器反馈值在决策树上游走,直到走到叶子节点,回答答案即可。
一些需要注意的细节;
- 因为所有答案被归一化成四种情况,因此在回答需要按照映射情况将答案映射回去。
- 每次的询问问题不一定出自于当前答案集合,直接从全局所有答案中(共 \(256\) 种)枚举选择即可,但要注意不要让映射数组溢出,最方便的方法就是直接不管任何情况,在保证归一化模型的个数满足下,任意挑选其余没有出现的数字将映射数组填满 \(4\) 个。
- 在当前数字个数已经满 \(4\) 的情况下,没有必要把之后的确定个数问题全部问完,直接开始下一步即可。
- 确定 \(9\) 的个数以后同样需要确定是否为
9999。
#include<bits/stdc++.h>
#define pii pair<int,int>
using namespace std;
const int N=500;
int rt[4],rcnt(0);
vector<pii> d;
vector<int> sta;
struct Node{
int q;
int son[5];
vector<int> ans;
}t[4][N];
int bulls(int S,int T){
int sum(0);
for(int tim(4);tim--;){
sum+=((S%10)==(T%10));
S/=10,T/=10;
}
return sum;
};
int B(int qry,vector<int> s){
int maxn(0);
int se[5]={0,0,0,0,0};
for(auto val:s) se[bulls(qry,val)]++;
maxn=max({se[0],se[1],se[2],se[3],se[4]});
return maxn;
}
void dfs(int &pos,vector<int> s,int opt){
if(!s.size()) return pos=-1,void();
if(!pos){
pos=++rcnt;
memset(t[opt][pos].son,0,sizeof(t[opt][pos].son));
}
t[opt][pos].ans=s;
if(s.size()==1) return;
int minn(100),qry(0);
for(auto val:sta){
if(minn>B(val,s)){
minn=B(val,s);
qry=val;
}
}
t[opt][pos].q=qry;
vector<int> cla[5];
for(auto val:s){
int cnt=bulls(qry,val);
cla[cnt].emplace_back(val);
}
for(int i=0;i<=4;++i) dfs(t[opt][pos].son[i],cla[i],opt);
}// 0001
void print(int num,char ch){
cout<<ch<<' ';
string s("");
for(int i=1;i<=4;++i){
s+=char(d[num%10].second+'0');
num/=10;
}
reverse(s.begin(),s.end());
cout<<s<<endl;
cout.flush();
return;
}
void query(int op){
int pos(rt[op]);
for(;pos>0&&t[op][pos].ans.size()!=1;){
print(t[op][pos].q,'?');
int val;cin>>val;
pos=t[op][pos].son[val];
}
if(pos>0&&t[op][pos].ans.size()==1) print(t[op][pos].ans[0],'!');
return;
}
void sol(){
d.clear();
vector<int> cnt(10);
int sum(0);
for(int i=0;i<9;++i){
cout<<"? "<<i<<i<<i<<i<<endl;
cin>>cnt[i];
if(cnt[i]==4){
cout<<"! "<<i<<i<<i<<i<<endl;
return;
}
sum+=cnt[i];
if(sum==4) break;
}
cnt[9]=4-sum;
if(cnt[9]==4){
cout<<"! 9999"<<endl;
return;
}
bool f3(0);
int op(-2);
for(int i=0;i<=9;++i){
if(cnt[i]) d.emplace_back(cnt[i],i),op++;
if(cnt[i]==3) f3=1;
}
for(int i=0;i<=9;++i){
if(cnt[i]) continue;
if(d.size()<4) d.emplace_back(cnt[i],i);
else break;
}
sort(d.begin(),d.end(),greater<pii>());
if(!op&&!f3) op=3;
query(op);
cout.flush();
}
void init(int op){
vector<function<void(int&,vector<int>,int)>> dfss={dfs,dfs,dfs,dfs};
vector<int> rts;
if(!op){
rts.emplace_back(1);
rts.emplace_back(10);
rts.emplace_back(100);
rts.emplace_back(1000);
}
else if(op==1){
rts.emplace_back(12),rts.emplace_back(21);
rts.emplace_back(102),rts.emplace_back(201);
rts.emplace_back(120),rts.emplace_back(210);
rts.emplace_back(1002),rts.emplace_back(2001);
rts.emplace_back(1020),rts.emplace_back(2010);
rts.emplace_back(1200),rts.emplace_back(2100);
}else if(op==2){
rts.emplace_back(123),rts.emplace_back(132),rts.emplace_back(231);
rts.emplace_back(213),rts.emplace_back(312),rts.emplace_back(321);
rts.emplace_back(1023),rts.emplace_back(1032),rts.emplace_back(1230);
rts.emplace_back(1203),rts.emplace_back(1302),rts.emplace_back(1320);
rts.emplace_back(2013),rts.emplace_back(2031),rts.emplace_back(2130);
rts.emplace_back(2103),rts.emplace_back(2301),rts.emplace_back(2310);
rts.emplace_back(3012),rts.emplace_back(3021),rts.emplace_back(3120);
rts.emplace_back(3102),rts.emplace_back(3201),rts.emplace_back(3210);
}
else{
rts.emplace_back(1100);
rts.emplace_back(1010);
rts.emplace_back(1001);
rts.emplace_back(110);
rts.emplace_back(101);
rts.emplace_back(11);
}
dfss[op](rt[op],rts,op);
}
void dfs_s(int k,int tmp){
if(k==5) return sta.push_back(tmp);
for(int i=0;i<=3;++i){
dfs_s(k+1,tmp*10+i);
}
}
int main(){
int T(1);
dfs_s(1,0);
for(int i=0;i<=3;++i) init(i);
cin>>T;
while(T--) sol();
}

浙公网安备 33010602011771号