3 条题解

  • 2
    @ 2024-9-29 8:24:39

    题解

    思路

    考虑直接构造。

    解题方法

    容易发现 nn 一定是某一段的最大值,故答案一定是 nn 的因数。

    如果 2m>n2m>n,则构造 n+12\dfrac{n+1}{2} 位置是 nn,其他位置乱填,此时任意一个区间必然包含 nn,答案为 nn

    其余情况至少有两个最大值不同的段,考虑现在 xx 的倍数只有 nx\dfrac{n}{x} 个,其中 xx 是答案。

    x>mx>m,则必有一段长为 mm 的段没有 xx 的倍数,故 xmx\leq m

    所以猜想此时答案是 mm 以下最大的 nn 的因数。

    考虑构造:x,1,...,x1,2x,x+1,...,2x1,3x,...x,1,...,x-1,2x,x+1,...,2x-1,3x,...

    然后就做完了。

    复杂度

    时间复杂度: O(Tn)O(Tn)

    空间复杂度: O(1)O(1)

    Code

    #include<bits/stdc++.h>
    using namespace std;
    int main(){
    	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    	int T;cin>>T;
    	while(T--){
    		int n,m;cin>>n>>m;
    		if(m*2>n){
    			int cnt=0;
    			for(int i=1;i<=n;++i)if(i==(n+1)/2)cout<<n<<" ";else cout<<(++cnt)<<" ";
    			cout<<'\n';
    			continue;
    		}
    		int T=1;
    		for(int i=m;i>=1;--i)if(n%i==0){T=i;break;}
    		int cnt=0;
    		for(int i=1;i<=n/T;++i){
    			cout<<T*i<<" ";++cnt;
    			for(int j=1;j<T&&cnt<n;++j)cout<<(i-1)*T+j<<" ",++cnt;
    		}
    		cout<<'\n';
    	}
    	return 0;
    }
    
    • 2
      @ 2024-9-28 21:32:07

      思路

      貌似跟官方题解不一样?

      我们考虑最优情况下,对答案造成贡献的数会被我们放在什么位置。

      发现下标为 mm 的倍数能够“控制”的数是最多的,所以我们考虑将数填入下标为 mm 的倍数的地方。

      接下来我们来考虑答案。不难发现 nn 一定是对答案有贡献的;其次 nn 最多只能完全“控制” m1m-1 个数。

      这就意味着我们可以枚举 [nm,n)[n-m,n) 中的每一个值,将其作为可能的第二小的有贡献的数,计算其与 nngcd\gcdmax\max 即可。

      然后对于剩余的没有填的空位,降序将剩余的数填入即可。

      Code

      #include<bits/stdc++.h>
      using namespace std;
      #define fi first
      #define sc second
      #define pii pair<int,int>
      #define pb push_back
      #define umap unordered_map
      #define mset multiset
      #define pq priority_queue
      #define ull unsigned long long
      #define i128 __int128
      const int maxn=1e6+10;
      int n,m,a[maxn],vis[maxn];
      void solve(){
          cin>>n>>m;
          int maxx=0,maxi=0;
          for(int i=1;i<=m;i++) if(maxx<__gcd(n,n-i)) maxi=n-i,maxx=__gcd(n,i);
          int num=n;
          for(int i=m;i<=n;i+=m) a[i]=num,vis[num]=1,num-=maxx;
          vector<int> vec;
          for(int i=n;i;i--) if(!vis[i]) vec.pb(i);
          int z=0;
          for(int i=1;i<=n;i++) if(!a[i]) a[i]=vec[z++];
          for(int i=1;i<=n;i++) cout<<a[i]<<" ",a[i]=vis[i]=0;
          cout<<endl;
      }
      int main(){
          ios::sync_with_stdio(false);
          cin.tie(0),cout.tie(0);
          int t=1;
          cin>>t;
          while(t--) solve();
          return 0;
      }
      
      • 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;
        }
        
        • 1

        信息

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