题意
要求构造一个数列 (a_1,a_2,...,a_n),满足 (1le a_ile 10^9),存在且仅存在 (m) 对三元组 ((i,j,k)) 满足 (a_i+a_j=a_k,1le i<j<kle n)
题解
看了官方题解写的,这里就翻译一下官方题解
显然数列 (1,2,...,n) 中存在三元组的数量最多。对于 (a_k=k),它前面的数列 (1,2,...,k-1) 两两之和等于 (k),那么对于 (a_k),存在 (lfloorfrac{k-1}{2}
floor) 对三元组。
显然最多可以有 (sum_{k=1}^{n}lfloorfrac{k-1}{2}
floor) 对三元组,如果 (m) 大于这个值,显然构造不出来。
如果可以构造,那么找到位置 (k) 满足 (sum_{i=1}^{k}lfloorfrac{i-1}{2}
floor le m) 且 (sum_{i=1}^{k+1}lfloorfrac{i-1}{2}
floor > m),
前 (k) 位保持 (a_i=i),第 (k+1) 位就只应该与前缀 (1,2,...,k) 构成 (m-sum_{i=1}^{k}lfloorfrac{i-1}{2}
floor) 个三元组。
根据之前构造三元组的规律,可以发现在 (1,2,...,k) 中,长度为 (l*2) 的后缀再添上一个项 (k-2*l+1+k) 可以构成 (l) 个三元组,
那么因为我要 (m-sum_{i=1}^{k}lfloorfrac{i-1}{2}
floor) 个三元组,就要添上一个 (k-2*(m-sum_{i=1}^{k}lfloorfrac{i-1}{2}
floor)+1+k)。
到这里,我们用了 (k+1) 项将 (m) 个三元组都凑齐了,剩余的项一个三元组都不能产生。
因为按照这个构造规律,前 (k+1) 项不可能大于 (5000),那么其他项只需要从 (10^8) 开始依次递增 (10^4) 就行了。
代码
#include <iostream>
#include <vector>
using namespace std;
int n,m,a[5050];
int main(){
cin>>n>>m;
int pos=0,sum=0;
while(pos<n&&sum+pos/2<=m) sum+=pos/2,pos++;
if(pos==n&&sum<m) return printf("-1
"),0;
for(int i=1;i<=pos;i++) printf("%d ",i);
if(pos==n) return 0;
printf("%d ",2*pos+1-2*(m-sum));
for(int i=pos+2;i<=n;i++) printf("%d ",(int)(1e8+1e4*(i-pos-2)));
return 0;
}