原题链接:B. Phoenix and Beauty
原题截图:
题目大意:
大概就是给出一个长度为n数组a,需要在其中加入一些元素,使得这个数组的任意一段长度为k的子数组(subarray)的元素之和都相等
输出加入这些元素后,数组的长度并输出数组
解题思路:
假设数组处理完之后的结果为数组b,那么来看看这个数组有什么特点。
∑
i
=
s
s
+
k
−
1
b
[
i
]
\sum_{i=s}^{s+k-1} b[i]
∑i=ss+k−1b[i]=
∑
i
=
s
+
1
s
+
k
b
[
i
]
\sum_{i=s+1}^{s+k} b[i]
∑i=s+1s+kb[i],则b[s]=b[s+k]
即处理完之后的数组需要满足b[s]=b[s+k]——这就意味着处理后的数组有一个k的周期,看看出题者的提示:
- 处理之前的数组长度为n(n<=100),周期k(k<=100)
- 处理之后的数组长度m(m<=1e4)
- 那么将原数组中所有的元素扩充为一个长度为k的周期即可,故最终m=n*k
由于只能向数组中加入元素而不能从数组中删除元素,那么原数组中的元素必然是数组周期中的一个部分,所以可以统计元素种类cnt,如果cnt>k,则无法形成一个长度为k的周期,故无解
AC代码:
#include<cstdio>
#include<cstring>
using namespace std;
const int len=110;
int main(){
int t,n,k,a,cnt,vis[len],seg[len];
scanf("%d",&t);
while(t--){
memset(vis,0,sizeof(vis));
cnt=0;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%d",&a);
if(!vis[a]){
cnt++;
}
vis[a]=1;
}
if(cnt>k){
printf("-1\n");
}
else{
printf("%d\n",k*n);
a=k-cnt;
cnt=0;
for(int i=1;i<=100;i++){
if(vis[i]){
seg[++cnt]=i;
}
else if(a){
a--;
seg[++cnt]=i;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=k;j++){
printf("%d ",seg[j]);
}
}
printf("\n");
}
}
return 0;
}