1 条题解
-
0
很厉害的构造题。下文所述中一个 进制数的第 位为从左往右数第 位。
考虑对于一个进制 ,若能构造出长度为 的答案,则一定能构造出长度为 的答案:因为若 $2\times \overline{d_1d_2\cdots d_n}=\overline{d_{p_1}d_{p_2}\cdots d_{p_n}}$,那么一定有 $2\times \overline{d_1d_2\cdots d_{i-1}(B-1)d_i\cdots d_n}=\overline{d_{p_1}d_{p_2}\cdots d_{p_{i-1}}(B-1)d_{p_i}\cdots d_{p_n}}$,其中 表示在长度为 的原数中某个向前一位进位的数位;即在第 位与第 位中插入了一个 必然也能满足条件。于是问题转换为:对于每个 找出最小的 使得 有解。
大胆猜测对于 ,最小的满足条件的 不大——事实证明存在较少个 使得 ,其它情况下均满足 。于是可以提出一个十分暴力的做法:
枚举原数 的每一位对应 的哪一位(即确定一个排列 ),再枚举 中每一位有没有是否有向前一位进位,之后就可以得到关于 的 个方程——是可以解出所有 的。
具体地,对于一个排列 ,连边 ,可以得到若干个环。每条边代表的方程是如下的形式:令 表示 是否向 进位,如果进位为 否则为 ,则方程为 。
对于一个环 ,通过如下方法解出所有 的值:将 用一个关于 的一次函数表示,接着就可以表示 ,最后由于 也有一个方程,所以能确定 使得 ,得出 的值后又能顺次推出其他的 ;最后检查一下所有解出的 是否满足 即可。
如果你被卡常,下载数据后发现 跑得最慢,打表一下就过了。
放代码:
#include<bits/stdc++.h> using namespace std; const int N=2e5; vector<int> vl[N+1],vr[N+1]; pair<vector<int>,vector<int> > solve(int B){ if(B==32131){ return make_pair( vector<int>({7545,15090}), vector<int>({30181,28232,24334,3772,16537,943,1886}) ); } // 特判 for(int n=2;;n++){ vector<int> p(n); iota(p.begin(),p.end(),0); do{ for(int S=2;S<1<<n;S+=2){ bool f=true; vector<bool> b(n); vector<int> r(n,-1); for(int i=0;i<n&&f;i++) if(!b[i]){ int x=i; vector<int> v; while(!b[x])v.emplace_back(x),b[x]=true,x=p[x]; pair<int,int> lf(1,0); // 一次函数 for(int i:v)lf=make_pair(lf.first*2,lf.second*2+(S>>i+1&1)-(S>>i&1)*B); if(lf.second%(lf.first-1))f=false; // 无整数解 else{ r[v[0]]=-lf.second/(lf.first-1); for(int i=1;i<v.size();i++) r[v[i]]=r[v[i-1]]*2+(S>>v[i-1]+1&1)-(S>>v[i-1]&1)*B; } // 顺次推出所有值 } for(int i=0;i<n&&f;i++) f&=0<=r[i]&&r[i]<B; if(f){ for(int i=0;i<n;i++) if(S>>i&1){ vector<int> L,R; for(int j=0;j<i;j++) L.emplace_back(r[j]); for(int j=i;j<n;j++) R.emplace_back(r[j]); return make_pair(L,R); } } } // 枚举进位 }while(next_permutation(p.begin(),p.end())); // 枚举排列 } } int main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t; cin>>t; while(t--){ int n,b; cin>>n>>b; if(vl[b].empty())tie(vl[b],vr[b])=solve(b); if(vl[b].size()+vr[b].size()>n){cout<<"-1\n"; continue;} for(int i:vl[b])cout<<i<<' '; for(int i=0;i<n-vl[b].size()-vr[b].size();i++) cout<<b-1<<' '; for(int i:vr[b])cout<<i<<' '; cout<<'\n'; } return 0; }
- 1
信息
- ID
- 7259
- 时间
- 2000ms
- 内存
- 512MiB
- 难度
- 10
- 标签
- 递交数
- 3
- 已通过
- 1
- 上传者