题解:P11277 世界沉睡童话

stswkl

2024-11-15 10:07:09

Solution

题意

题目传送门

思路

先从部分分开始考虑。

k=0

k=0 时,不存在一个数是另外一个数的的倍数,考虑到 a 中的最大值不超过 2n-1,若我们输出 n\sim 2n-1,则刚好满足要求。

k\le n-1

k=0 时同上,而 k=n-1 时我们输出 1n\sim 2n-2 即可,接下来考虑 1\le k<n-1 即可。

注意到若恰好有 2 个相同的数 x 且满足 x\ge n,则它们互相可以有 1 对倍数关系,所以当 k=1k=2 时,我们输出 k 对相同的大于等于 n 的数即可。同时可以发现若恰好有 3 个相同的数 x 且满足 x\ge n,则它们互相可以有 3 对倍数关系,所以当 k=3 时我们输出 3 个相同的大于 n 的数即可。

那要是 k\ge 4 呢?我们可以输出 \left\lfloor\frac{k}{3}\right\rfloor3 个相同的数(每次输出的数不能相同),这样就可以保证剩下的 k\le 2,再按照 k\le 2 的方式输出即可。

正解

从上一个部分分我们已经可以知道一些与正解相关的解法了,接下来把上面的做法推广到 k>n 即可。

n-1\le k<(n-1)+(n-2) 时,我们可以先输出 1,因为后面的所有数必然是 1 的倍数,所以必然构成 n-1 对倍数关系,所以使 k\gets k-(n-1),接下来按照 k<n-1 的方式输出即可。

(n-1)+(n-2)\le k<(n-1)+(n-2)+(n-3) 时,我们可以在上面的基础上再次输出 1,这个 1 可以与后面的数构成 n-2 对倍数关系,所以在上面的基础上再使 k\gets k-(n-2),然后按照 k<n-1 的方式输出。

从上面的处理方式我们可以发现,若 k\ge\sum_{i=1}^nn-i 且此时的 i 为满足条件的 i 中最大的,则需要输出 i1,然后按照部分分的思路输出即可。

代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
int ans[N];
signed main()
{
    int n,k;
    cin>>n>>k;
    int m=n-1,cnt=1,tot=0;
    while(cnt<=n&&k-n+cnt>=0)k-=n-cnt,cnt++,ans[++tot]=1;
    while(k>=3)
    {
        ans[tot+1]=ans[tot+2]=ans[tot+3]=++m;
        tot+=3,k-=3;
    }
    for(int i=1;i<=k;i++)ans[tot+1]=ans[tot+2]=++m,tot+=2;
    while(tot<n)ans[++tot]=++m;
    for(int i=1;i<=tot;i++)cout<<ans[i]<<' ';
    return 0;
}