1 条题解
-
0
首先假设 ,则 。
通过 的部分分可以猜测合法条件为 及其轮换形式。
首先 较显然,因为长度为 的 至少有长为 的 。
然后考虑 时的情况,首先 ,考虑 中元素在 中出现的顺序 , ,其次 ,那么 ,这显然是不可能的。
考虑 时的构造,考虑在 一定时 尽可能大的经典构造:若干值域递减的上升序列和若干值域递增的下降序列。
那么直接运用之, 为 个长度为 的上升序列, 为 个长度为 的下降序列,则 为 个值域递增的长度为 的下降序列值域递减地重复 次,此时 合法。
注意到我们只要取出三个排列中值为 $[1,2,\dots,a],[1,ac+1,2ac+1,\dots,(b-1)ac+1],[1,a+1,2a+1,\dots,(c-1)a+1]$ 的元素构成的子序列(即 之间的 中元素),此时得到 个元素的排列,如果 ,随便选一些剩下的元素放进去即可。
那么只要考虑 的情况,如果 ,则求 的解然后在末尾插入 即可。
否则 ,容易发现此时必有 ,即 ,在 的基础上交换 即可。
那么我们就给出了所有 的构造方法。
时间复杂度 。
代码:
#include<bits/stdc++.h> #define ll long long using namespace std; const int MAXN=2e5+5; void solve() { ll n,a,b,c,ty,m; cin>>n>>a>>b>>c>>ty,m=n; if(a*b*c<n||a+b>c+n||a+c>b+n||b+c>a+n) return cout<<"No\n",void(); cout<<"Yes\n"; if(!ty) return ; int k=0; for(;n&&(a-1)*(b-1)*(c-1)>=n-1;++k,--a,--b,--c,--n); basic_string <int> B,C; if(!n); else if(a+b+c-2>n) { for(int i=n-1;~i;--i) B+=i,C+=i; swap(B[0],B[1]),swap(C[1],C[2]); } else { map <ll,int> X; vector <array<ll,2>> Y,Z; auto ins=[&](ll x) { X[x]=0,Y.push_back({-(x/a),x}),Z.push_back({x/a/c,-x}); }; ins(0); for(int i=1;i<a;++i) ins(i); for(int i=1;i<b;++i) ins(a*c*i); for(int i=1;i<c;++i) ins(a*i); for(int i=0;i<n&&(int)X.size()<n;++i) if(!X.count(i)) ins(i); sort(Y.begin(),Y.end()),sort(Z.begin(),Z.end()); int t=0; for(auto &o:X) o.second=t++; for(auto o:Y) B+=X[o[1]]; for(auto o:Z) C+=X[-o[1]]; } for(int i=n;i<m;++i) B+=i,C+=i; for(int i=0;i<m;++i) cout<<i+1<<" \n"[i==m-1]; for(int i=0;i<m;++i) cout<<B[i]+1<<" \n"[i==m-1]; for(int i=0;i<m;++i) cout<<C[i]+1<<" \n"[i==m-1]; } signed main() { ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); int _; cin>>_; while(_--) solve(); return 0; }
- 1
信息
- ID
- 7099
- 时间
- 4000ms
- 内存
- 2048MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者