zoukankan      html  css  js  c++  java
  • 牛客练习赛51 E-数列

    E-数列

    题目链接:https://ac.nowcoder.com/acm/contest/1083/E

    题目描述:
    小乔有一个长度为n的整数数列,最开始里面所有的值都为0,小乔需要将在1…n的每一个位置填入一个大于0的正整数,得到一个新的数列,并且这个数列所有数的和不超过m,小乔对这个数列会有一个喜爱度,小乔对这个数列的喜爱度为满足2<=i<=n并且a[i]=a[i-1]+1的i的个数。现在给出n,m,请你制定一种填数方案,最大化小乔对数列的喜爱度。方案可能有多种,你只需要输出任意一种即可。

    题解:

    我们先定义一个如果对于一段数列a[i],a[i+1]...a[j-1],a[j] 如果a[k]=a[k-1]+1(i+1<=k<=j)同时也满足a[i]!=a[i-1]+1||a[j+1]!=a[j]+1,我们称这样一段数列为段,假设数列中有sum段这样的数列,最大

    喜爱度为n-sum,因为我们可以自由填数,对于任意一段可以填为(1,2,3...S)则其和为s*(s+1)/ 2;

    所以我们要使sum尽可能地小,并且所有段的总和要小于m;

    因此我们可以二分查找sum并且均分n,这样我们就能的到n/sum个段,其他的n%sum平分到n/sum段上,所以最后得到n%sum个长度为n/sum+1的段和sum-n%sum段长度为n/sum段

    最后输出就行了

    官方题解:https://m.nowcoder.com/discuss/248083?&headNav=acm

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    ll n,m;
    bool judge(ll mid)
    {
        return (n/mid+1)*(n/mid+2)/2*(n%mid)+(n/mid)*(n/mid+1)/2*(mid-n%mid)<=m;
    }
    void solve(ll ans)
    {
        ll cnt=1;
        for(int i=1;i<=n%ans;i++)
        {
            for(int j=1;j<=n/ans+1;j++)
            {
                cout<<j<<(cnt++==n?'
    ':' ');
            }
        }
        for(int i=1;i<=ans-n%ans;i++)
        {
            for(int j=1;j<=n/ans;j++)
            {
                cout<<j<<(cnt++==n?'
    ':' ');
            }
        }
    }
    int main()
    {
        cin>>n>>m;
        ll l=1,r=n;
        ll ans=n;
        while(l<=r)
        {
            ll mid=(l+r)>>1;
            if(judge(mid)) ans=mid,r=mid-1;
            else l=mid+1;
        }
        solve(ans);
        return 0;
     } 
  • 相关阅读:
    一张图看懂开源许可协议,开源许可证GPL、BSD、MIT、Mozilla、Apache和LGPL的区别
    常用Flex 布局scss
    设置npm registry的几种方法
    JavaScript计算平方数的三种方法
    NPM 使用介绍
    x 的 y次幂科学计数法
    Docker 容器使用
    使用dos的tree命令输出文件夹树
    赣州(虔州)历史文化
    vue通过$ref获取不到元素样式?
  • 原文地址:https://www.cnblogs.com/tombraider-shadow/p/11486630.html
Copyright © 2011-2022 走看看