1 条题解

  • 1
    @ 2021-6-15 12:24:47

    一个纯粹的构造题。本来不想设 op1op1 的限制的,因为对正解提示性太大,但是没有这限制指不定有什么更简单的做法(

    毕竟题源是 MO 题,其中的官方解答给的是 op1=0op1=0 的解答,op1=1op1=1 是我自己的做法。

    先讲下部分分。

    n7n \le 7 直接手玩,或者写个爆搜随便搞搞,打个表就完了。

    而且样例给了 1,2,3,41,2,3,4 然后 n7n \le 7 只有 33 个点,这些数据是什么你应该已经知道了,那就面向数据编程吧!

    接下来,我们先判无解。显然可以算两次。

    $$\sum_{i=1}^{\frac{n(n-1)}{2}}(a_{x_i}+a_{y_i}+2k_i)=\sum_{i=1}^{n(n-1)}i, $$$$(n-1)\sum_{j=1}^{n}a_j \equiv \dfrac{n(n-1)(n^2-n+1)}{2}\pmod{2}. $$

    显然当 n3(mod4)n \equiv 3 \pmod{4} 时左边为偶数,右边为奇数,矛盾!

    另外我们有其他情况均有解。我们通过构造说明。

    首先做 op1=0op1=0nn 为偶数的情况。设 n=2tn=2t。则显然取 ai=(i1)(n1)a_i=(i-1)(n-1),然后对 1it1 \le i \le tn1n-1x=i,y=n+1ix=i,y=n+1-i,第 jj 次取 k=jk=j。显然这样满足题目要求。

    op1=0op1=0nn 为奇数的情况当时的官方解答很复杂,如果有人有兴趣可以在评论区说,我后续可能会放(gu)上(gu)来(gu)。如果有人有简单的解法完成这个部分分可以私信我,那说明我如果不设 op1op1 的限制这题就会被水过。

    下面直接讲 op1=1op1=1。发现我们每一对 x,yx,y 出现的次数在 nn 增大时都不减,尝试归纳构造。

    我们自然地想到最简单的情况:取 ai=i1a_i=i-1。我们在此基础上尝试构造。

    首先我们思考如何处理 4t4t+14t \to 4t+14t+14t+24t+1 \to 4t+2nn+1n \to n+1 的情况。显然此时我们要将 n(n1)+1n(n-1)+1n(n+1)n(n+1) 的正整数分成 nn 组,使得每组两数之差恰好取遍 11nn 各一次。这就是P7510 铃解缀

    然后考虑 4t24t4t-2 \to 4tnn+2n \to n+2 的情况。显然我们要将 n(n1)+1n(n-1)+1(n+1)(n+2)(n+1)(n+2) 的正整数分成 2n+12n+1 组,使得每组两数之差取 11nn 各两次,n+1n+1 一次。这个的构造是容易的,具体如下(以下 xx 表示 n(n1)+x,n=4t2n(n-1)+x,n=4t-2):

    (2t,2t+n+1);(2t,2t+n+1); (2ti,2t+i),i=1,2,,2t1;(2t-i,2t+i),i=1,2,\dots,2t-1; (2t+n+1i,2t+n+1+i),i=1,2,,2t1;(2t+n+1-i,2t+n+1+i),i=1,2,\dots,2t-1; (2t+2n+2i,2t+2n+1+i),i=1,2,,2t1;(2t+2n+2-i,2t+2n+1+i),i=1,2,\dots,2t-1; (2t+3n+2i,2t+3n+1+i),i=1,2,,2t1.(2t+3n+2-i,2t+3n+1+i),i=1,2,\dots,2t-1.

    也可以见代码中相关部分理解。

    这样做是满足 op2=1op2=1 的限制的,只要稍作计算就能够证明。

    总时间复杂度 O(n2)O(n^2)

    Code:

    #include<cstdio>
    #define rg register
    int n,m,o;
    int cnt[3007];
    int res[3007][3007];
    int main()
    {
    	scanf(" %d %d %d",&n,&o,&o);
    	if(n&3^3)
    	{
    		printf("%d\n",n);
    		for(rg int i=0;i<n;++i)printf("%d ",i);
    		puts(""),res[1][cnt[1]=1]=1;
    		for(rg int k=2,t;k<n;++k)
    		{
    			t=k*(k-1);
    			if(k&2)
    			{
    				++k,m=(k+1)>>1;
    				res[k][++cnt[k]]=t+m;
    				for(rg int i=1;i<m;++i)
    				{
    					res[i<<1][++cnt[i<<1]]=t+m-i;
    					res[i<<1][++cnt[i<<1]]=t+k+m-i;
    					res[(i<<1)-1][++cnt[(i<<1)-1]]=t+(k<<1)+m-i;
    					res[(i<<1)-1][++cnt[(i<<1)-1]]=t+(k<<1)+k+m-i-1;
    				}
    			}
    			else
    			{
    				m=k>>2;
    				if(k&1)
    				{
    					res[1][++cnt[1]]=t+1;
    					res[k][++cnt[k]]=t+k;
    					res[k-2][++cnt[k-2]]=t+m+2;
    					res[k-1][++cnt[k-1]]=t+((m+1)<<1);
    					res[k>>1][++cnt[k>>1]]=t+k+(k>>1);
    					for(rg int i=1;i<m;++i)
    					{
    						res[i<<1][++cnt[i<<1]]=t+((m+1)<<1)-i;
    						res[i<<1|1][++cnt[i<<1|1]]=t+k+(m<<1)-i;
    						res[k-(i<<1|1)][++cnt[k-(i<<1|1)]]=t+k+i;
    						res[k-((i+1)<<1)][++cnt[k-((i+1)<<1)]]=t+2+i;
    					}
    				}
    				else
    				{
    					res[1][++cnt[1]]=t+1;
    					res[k-1][++cnt[k-1]]=t+m+2;
    					res[k>>1][++cnt[k>>1]]=t+k+1;
    					res[k][++cnt[k]]=t+((m+1)<<1);
    					for(rg int i=1;i<m;++i)
    					{
    						res[i<<1][++cnt[i<<1]]=t+((m+1)<<1)-i;
    						res[k-(i<<1)][++cnt[k-(i<<1)]]=t+k+i+1;
    						res[k-(i<<1|1)][++cnt[k-(i<<1|1)]]=t+2+i;
    						res[i<<1|1][++cnt[i<<1|1]]=t+k+(m<<1|1)-i;
    					}
    				}
    			}
    		}
    		for(rg int i=1;i<n;++i)
    		{
    			for(rg int j=1;j<=n-i;++j)
    			{
    				printf("%d %d %d\n",j,j+i,res[i][j]-j+1);
    			}
    		}
    	}
    	else puts("-1");
    	return 0;
    }
    
    • 1

    信息

    ID
    147
    时间
    1000ms
    内存
    128MiB
    难度
    6
    标签
    递交数
    37
    已通过
    12
    上传者