Codeforces Round #517 C.Cram Time

这道题当初还觉得是什么高深莫测的算法,dp仍是搜索剪枝,没想到竟然是道普普统统的贪心+模拟。这都没看出来,服了。c++

这道题错在两个地方:算法

  • 数学推导有问题。我推导到了n(n+1)/2<=(a+b),可是接下来犯错了。我没有继续推导n最大时的不等式,而是想固然的计算了**floor(sqrt(2*(a+b))),由于我以为n和n+1不就相差1嘛,稍微大一点,开根号舍去小数位数不就完了嘛。可是还真不是这样的。当n最大时,设为N,咱们只有不等式推导的N<=sqrt(2(a+b))<=N+1**,而不能肯定开方得数到底和N差几,可能差小于1,那向下取整对,也可能差大于1,那向下取整就错(如10亿)。这时候,就要加个循环,不断向下减一便可。

之后必定记住,求n(n+1)<x的最大整数n,向下取整后,还要有一步循环相减,无论这一步是否有效spa

  • 算法设计有问题。讲真,虽然上面的式子我很早就推出来了,可是我一直不知道该拿什么策略填。没想到正解的策略这么的简单,简单到弱智。。。仍是脑子不灵光啊。其实由于我没有意识到,既然能够肯定可以填充的最长耗时学案编号k,那就能够肯定,全部的从耗时1~k的全部学案,必定均可以填到这两天里,只是如何填的策略问题。正确策略是,从学案耗时k开始填,k,k-1,k-2,...2,1,每个都填到两天中能填进去的那天,就这么简单。。。
#include <bits/stdc++.h>
using namespace std;
vector<int> va,vb;
int main()  {
    int a,b;
    cin>>a>>b;
    int n=sqrt(2.0*(a+b));
    while (n*(n+1)/2>(a+b))    n--;
    //cout<<"n=\t"<<n<<endl;
    for (int i=n;i>=1;i--)  {
        if (a>=i)   {a-=i;va.push_back(i);}
        else    vb.push_back(i);
    }
    cout<<va.size()<<endl;
    if (!va.empty())    cout<<va[0];
    for (int i=1;i<(int)va.size();i++)
        cout<<' '<<va[i];
    cout<<endl;
    cout<<vb.size()<<endl;
    if (!vb.empty())    cout<<vb[0];
    for (int i=1;i<(int)vb.size();i++)
        cout<<' '<<vb[i];
    cout<<endl;
    return 0;
}
相关文章
相关标签/搜索