3 条题解

  • 0
    @ 2024-10-3 18:34:10

    P11132 【MX-X5-T4】「GFOI Round 1」epitaxy

    基于次大值的构造。

    考虑到如果最大值和次大值都出现那么结果一定为 11。而如果次大值在序列中出现 2m12m-1 次,则一定会与最大值一起出现,这是不好的。

    因此,我们构造把次大值放在序列开头,之后最大值必须要放在前 mm 个位置。这中间有 m2m-2 个空位,我们填上 n2nm1n-2\sim n-m-1,剩下的位置需要填入一个 1nm1\sim n-m 的排列,这是一个完全相同的子问题。

    如果我们不把空位填上 n2nm1n-2\sim n-m-1,就是希望能更改答案序列中的值。而这种更改上述构造方式也能做到,所以直接这样构造是没有问题的。另外,也可以把次大值放在序列结尾,但是只是改变一个方向,本质相同。如果不把次大值贴紧开头,与这个构造也是等价的,但变得不好处理。

    我们发现答案序列中的数构成等差序列且公差为 nn 的约数时才能更新答案,所以我们枚举公差,按照上述方式构造即可。

    注意有可能 mm 过大,最小值不能出现 2m12m-1 次,这个时候把最大值放中间就好了。我因为这个边界条件卡了一整场,警示后人。

    #include <bits/stdc++.h>
    using namespace std;
    long long t,n,m,ans=0;
    int main()
    {
    	scanf("%lld",&t);
    	while(t--)
    	   {
    	   	scanf("%lld%lld",&n,&m);
    	   	if(m>n/2)
    	   	   {
    	   	   	for(int i=1;i<=n/2;i++)printf("%lld ",1ll*i);
    	   	   	printf("%lld ",n);
    	   	   	for(int i=n/2+2;i<=n;i++)printf("%lld ",i-1ll);
    		   }
    	   	else
    		   	{
    		   	bool flag=1;
    			for(int i=m;i>=2;i--)
    			   	if(n%i==0)
    			   	    {
    			   	    long long now=n;
    			   	    flag=0;
    				   	while(now>0)
    				   	    {
    				   	    printf("%lld ",now-1);
    				   	    for(int j=1;j<=i-2;j++)printf("%lld ",now-1-j);
    				   	    printf("%lld ",now);
    				   	    now-=i;
    						}
    					break;
    					}
    			if(flag)for(int i=1;i<=n;i++)printf("%lld ",i);
    		    }
    		printf("\n");
    	   }
    	return 0;
    }
    

    信息

    ID
    69
    时间
    3000ms
    内存
    512MiB
    难度
    5
    标签
    递交数
    446
    已通过
    92
    上传者