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;
}
相關文章
相關標籤/搜索