zoukankan      html  css  js  c++  java
  • BZOJ 3119 Book (贪心+数学推导)

    手动博客搬家: 本文发表于20171029 22:49:41, 原地址https://blog.csdn.net/suncongbo/article/details/78388925

    URL: http://www.lydsy.com/JudgeOnline/problem.php?id=3119

    题目大意:
    给定一个序列v[]的长度n (n<=1e5), 第一个元素的值p以及序列中所有元素的和m (m在long long范围内), 规定对于任意的2<=i<=n, 都有v[i]=v[i-1]+a或v[i]=v[i-1]-b, 同时给定a,b, 确定一组可能的v[]至并输出。

    思路分析:
    为了方便起见,先将b变为输入数的相反数(即变为一个负数)。
    首先,考虑初始值x造成的影响: 它使得1至n的序列所有元素增加了x, 因此可以将这个值剔除,这样和变成了(m-np).
    其次,考虑第i个元素的值v[i]=v[i-1]+a造成的影响: 它使得i至n的序列中所有元素增加了a,使总和增加了((n+1-i)a).
    同理可得,若v[i]=v[i-1]+b (b为负数)则使总和增加了((n+1-i)b)
    在这里,我们称这次赋值对总和产生了((n+1-i))点影响。
    显然,所有的赋值对总和一共产生了(sum_{i=2}^n (n+1-i)=sum_{i=1}^{n-1} i=frac{1}{2}n(n-1))点影响。设其中+a产生的影响为x点,+b产生的影响为y点。由刚才的结论得:$$x+y=frac{1}{2}n(n-1)$$$$xa+yb=m-nx$$
    解二元一次方程组可得$$x=frac{1}{2}n(n-1)-y$$$$y=frac{frac{1}{2}an(n-1)-m+np}{a-b}$$
    于是只需构造方案即可。这一步比较简单。可以用贪心来实现。
    我们的目标是在1至n得正整数范围内找到一些互不相同数使得他们的和恰好是x,其余的数的和恰好是y, 因为(x+y=frac{1}{2}n(n-1)).因此,我们只需选出和为x的部分。考虑到$$1=1$$$$2=2, 3=2+1$$$$4=3+1, 5=3+2, 6=3+2+1$$$$7=4+3, 8=4+3+1, 9=4+3+2, 10=4+3+2+1$$$$...$$
    注:第i行能用的最大的数是i.
    因此,我们得到一种贪心策略: 从n开始,从大到小依次选择,如果剩余的x能够选上i就选,并且x-=i, 直至x==0为止,剩余的就是y.
    若为x, 则v[i]=v[i-1]+a; 否则v[i]=v[i-1]+b (b<0)
    但由于对总和产生了i点影响的是(n+i-1)号决策,因此输出时勿忘倒着输出。

    代码实现:
    (Memory: 920KB; Time: 376MS; Code: 614B)

    #include<cstdio>
    using namespace std;
    const int MAXN = 1e5;
    bool inc[MAXN+2];
    int main()
    {
        long long a,b,x,y,m,n,p;
        scanf("%lld%lld%lld%lld%lld",&n,&p,&a,&b,&m);
        b = -b;
        y = (a*n*(n-1)/2-m+n*p)/(a-b);
        x = n*(n-1)/2-y;
        long long cur = p;
        for(long long i=n-1; i && x; i--)
        {
            if(x>=i)
            {
                inc[i] = true;
                x-=i;
            }
        }
        printf("%lld",cur);
        for(long long i=n-1; i; i--)
        {
            if(inc[i]) cur+=a;
            else cur+=b;
            printf(" %lld",cur);
        }
        return 0;
    }
    
  • 相关阅读:
    剑指offer-矩形覆盖
    剑指offer-变态跳台阶
    剑指offer-跳台阶
    剑指offer-斐波那契数列
    剑指offer-旋转数组的最小数字
    剑指offer-用俩个栈实现队列
    剑指offer-重建二叉树
    剑指offer-从尾到头打印链表
    http头
    mysql-8.0解压缩版安装配置完整过程
  • 原文地址:https://www.cnblogs.com/suncongbo/p/10182400.html
Copyright © 2011-2022 走看看