• 牛客练习赛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;
     } 
  • 相关阅读:
    PAT 甲级1135. Is It A Red-Black Tree (30)
    AVL树模板
    定时器模板
    Listview模板
    Hash二次探测
    BFS小结
    STL之set篇
    完全二叉树-已知中序排序,输出广度排序
    BZOJ2037: [Sdoi2008]Sue的小球
    poj1157LITTLE SHOP OF FLOWERS
  • 原文地址:https://www.cnblogs.com/tombraider-shadow/p/11486630.html
Copyright © 2020-2023  润新知