原题题面:https://ac.nowcoder.com/acm/contest/33191/A
题目大意:给定大小为
n
(
1
≤
n
≤
1
e
5
)
n(1\leq n \leq1e5)
n(1≤n≤1e5)的数组
a
(
1
≤
a
i
≤
2
e
5
)
a(1\leq a_i\leq2e5)
a(1≤ai≤2e5),满足
∑
1
a
i
≤
1
2
\sum\frac{1}{a_i}\leq\frac{1}{2}
∑ai1≤21。求长度为
m
m
m的序列
c
c
c。基于序列
c
c
c,可以生成无限长的序列
b
b
b。满足
b
i
=
c
i
m
o
d
m
b_i=c_{i} mod _ {m}
bi=cimodm。
b
b
b必须满足其中任意连续
a
i
a_i
ai个数中,必有一个值为
i
i
i。
输出序列
c
c
c长度
m
(
1
≤
m
≤
1
e
6
)
m(1\leq m \leq1e6)
m(1≤m≤1e6),以及长为
m
m
m的序列
c
c
c
解题分析:
要充分利用条件!!!
因为
∑
1
a
i
≤
1
2
\sum\frac{1}{a_i}\leq\frac{1}{2}
∑ai1≤21,而实际上
∑
1
a
i
≤
1
\sum\frac{1}{a_i}\leq 1
∑ai1≤1就有可能有解了
再观察题目,可发现
a
i
a_i
ai没有规律,很容易产生冲突,而以2为底的数幂则不会产生冲突
(
见文末注释
1
)
(^{见文末注释1})
(见文末注释1)
两种条件一结合,应该想到可将每一个
a
i
a_i
ai转化成第一个小于等于
a
i
a_i
ai的整数次幂,这时的
∑
1
a
i
\sum\frac{1}{a_i}
∑ai1至多也小于等于1,会有解
接下来,便可以暴力构造,先选一个极大的m,如
m
=
2
19
m=2^{19}
m=219,再求出序列c
代码:
#include<iostream>
#include<algorithm>
using namespace std;
const int MXN=2e5+2;
struct Node{
int num,id;
}b[MXN];
int pw[21];
int ans[MXN];
template<class T> inline void read(T&x){
char c;
while(!isdigit(c=getchar()));
x=c^48;
while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+(c^48);
}
bool cmp(Node x,Node y){
return x.num<y.num;
}
inline void write(int x){
if(x/10>0) write(x/10);
putchar(x%10+'0');
}
int main(){
int n,a,k,id,ID,lim,i,j;
pw[0]=1;
for(i=1;i<=20;i++){
pw[i]=pw[i-1]*2;
}
read(n);
for(i=1;i<=n;i++){
read(a);
ID=lower_bound(pw+1,pw+1+20,a)-pw;
if(pw[ID]>a){
ID--;
}
lim=max(lim,pw[ID]);
b[i].id=i;
b[i].num=pw[ID];
}
sort(b+1,b+1+n,cmp);
for(i=1,k=1;i<=n;i++){
while(ans[k]) k++;
for(j=k;j<=lim;j+=b[i].num){
ans[j]=b[i].id;
}
}
write(lim); printf("\n");
for(i=1;i<=lim;i++){
if(ans[i]){
write(ans[i]); printf(" ");
} else {
putchar('1'); printf(" ");
}
}
printf("\n");
}
注释1:哈夫曼树的非冲突性,可以保证不会冲突且可以给出不受冲突的序列
https://blog.csdn.net/qq_29519041/article/details/81428934?ops_request_misc