Description
简单说一下题意吧。
就是输入一个长度为 \(m\),元素和为 \(n\) 的序列 \(a\),\(a\) 数组的定义就是题面中的含义。
你需要构造出一个 \(b\) 序列,同样也表示回文串的长度,使得只有全 1 的序列满足 \(a\) 和 \(b\) 这两个条件。
Solution
emm……看了 \(n\) 分钟没看懂题,然后 xrf 学长题都讲完了,听了个大概但还是不懂题,跑去找 xrf 学长帮我解释,又解释了 \(n\) 分钟才懂……
菜的真实。
“接口”,以及是奇数的 \(a_i\) 不得超过两个且必须在两边什么的可以直接去看第一篇题解,非常清晰 CCCCCOrz
这里讲一下构造方法。
经过无数次尝试,发现这样构造是可以的。
样例:
14 4
2 3 4 5
首先排完序之后,奇数被放到了两边(偶数随便排),即:
3 2 4 5
我们画个图构造一下:
蓝色的就是构造出的 \(b\) 序列,即:
4 2 4 4
不难发现,
\(b_1 = a_1 + 1\)
\(b_4 = a_4 - 1\)
多试几组样例发现这样构造确实是可以的(证明去看各位大佬的题解吧QwQ)
注意:
- 如果 \(a_m = 1\),那么最后一位直接删去即可。
- \(m = 1\) 时要特判,具体见代码。
- \(a_i\) 是奇数的数的个数大于 2 时,直接输出
Impossible
。
Code
#include <bits/stdc++.h>
using namespace std;
namespace IO{
inline int read(){
int x = 0, f = 1;
char ch = getchar();
while(!isdigit(ch)) ch = getchar();
while(isdigit(ch)) x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
template <typename T> inline void write(T x){
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
}
inline void print(int a[], int m){
write(a[1]), putchar(' ');
for(int i = 3; i <= m; ++i) write(a[i]), putchar(' ');
if(a[2]) write(a[2]), puts("");
}
}
using namespace IO;
const int N = 1e5 + 10;
int n, m, cnt;
int a[N], b[N];
inline bool cmp(int a, int b){
return (a & 1) > (b & 1);
}
int main(){
n = read(), m = read();
for(int i = 1; i <= m; ++i) a[i] = read(), cnt += (a[i] & 1);
if(cnt > 2) return puts("Impossible"), 0;
if(m == 1){
if(a[1] == 1) printf("1\n1\n1\n");
else printf("%d\n2\n1 %d\n", a[1], a[1] - 1);
return 0;
}
sort(a + 1, a + 1 + m, cmp);
print(a, m);
write(m - (a[2] == 1)), puts("");
a[1]++, a[2]--;
print(a, m);
return 0;
}
\[\_EOF\_
\]