1. 程式人生 > >清北學堂國慶day5解題報告

清北學堂國慶day5解題報告

space 枚舉 color stream pri font align code efi

Day5解題報告

張炳琪

時間安排::

T1:想了很久,一個多小時寫的暴力

T2:一小時左右

T3:一小時以內

答題情況和錯誤分析::

T1 30

考場上沒推出來,想復雜了,拆分的二進制只得了暴力分

T270

寫的比較穩妥的根號枚舉暴力

T360

寫了個剪枝搜索,打了個暴力

Tot::160

題目解析:

T1

先將數據從小到大排序,然後線性掃一遍,一邊掃一邊求和,當下一個數字比以前所求的所有數字之和還要大1以上的時候,就不滿足情況,這時應當終止並且輸出。

T2

正解是二分最小單個連續值區間,O1計算兩邊的值

歪解是開根號乘以二再減一也能A

我的方法是一種找連續區間的方法,但只是枚舉,所以過不了所有點

T3:從60%的數據中我們得到其實,這個題目搜索的復雜度已經不錯了,但是2^30依舊過不了,這時用了一個我以前沒用過的知識點,就是分成兩塊搜索,然後合並狀態,聽老師講完就比較好寫了;

合並的時候采用二分合並的方法,第一次搜索出所有狀態後對於狀態進行排序,首先按照鉆石個數,其次按照拿到的價值,之後第二次搜索對於每個得到的狀態二分找尋所有符合要求的條件

代碼:

T1

#include<cstdio>
#include<iostream> 
#include<algorithm>
#define MAXN 100100
using namespace std;
long
long note[MAXN]; int n; int main() { freopen("lost.in","r",stdin);freopen("lost.out","w",stdout); scanf("%d",&n); for(int i = 1;i <= n;i++) scanf("%lld",&note[i]); sort(note + 1,note + n + 1); long long tot = 0; for(int i = 1;i <= n;i++) { if
(note[i] > tot + 1) { break; } tot += note[i]; } cout << tot + 1; return 0; }

T2:

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath> 
using namespace std;
long long n;
int main()
{
    freopen("div.in","r",stdin);freopen("div.out","w",stdout);
    cin >> n;
    long long q = sqrt(n);
    long long ans = q * 2;
    if(q * (q + 1) > n)ans--;
    cout << ans ;
    return 0;
}

T3;

#include<cstdio>
#include<algorithm>
using namespace std;
struct Note{
    int k;
    int ver;
    double gai;
}note[923456];
double qian[31][9876];
int ver[31][9876];
int tp[31];
int top = 0;
int n,m;
int v[99];
double p[99];
double ans[99];
int zz;
void dfs(int step,int zuan,int mon,double gai)
{
    if(step == zz + 1)
    {
        top++;
        note[top].gai = gai;
        note[top].k = zuan;
        note[top].ver = mon;
        return;
    }
    dfs(step + 1,zuan + 1,mon,gai * (1 - p[step]));
    dfs(step + 1,zuan,mon + v[step],gai * p[step]);
}

int find(int k,int mon)
{
    int l = 1,r = tp[k];
    while(l + 1 < r)
    {
        int mid = (l + r) >> 1;
        if(ver[k][mid] >= mon)l = mid;
        else r = mid;
    }
    if(ver[k][r] >= mon)return r;
    if(ver[k][l] >= mon)return l;
    return -1;
}

void check(int zuan,int mon,double gai)
{
    for(int i = 0;i <= n - zuan;i++)
    {
        int zz = m - mon;
        int q = find(i,zz);
        if(q == -1)continue;
        ans[i + zuan] += qian[i][q] * gai;
        
    }
}

void rdfs(int step,int zuan,int mon,double gai)
{
    if(step == n + 1)
    {
        check(zuan,mon,gai);
        return;
    }
    rdfs(step + 1,zuan + 1,mon,gai * (1 - p[step]));
    rdfs(step + 1,zuan,mon + v[step],gai * p[step]); 
}

bool cmp(Note a,Note b)
{
    return a.k == b.k ? a.ver > b.ver : a.k < b.k; 
}

int main()
{
    freopen("diamond.in","r",stdin);freopen("diamond.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;i++)
    {
        scanf("%d%lf",&v[i],&p[i]);
        p[i] /= 100.0;
    }
    zz = n / 2;
    dfs(1,0,0,1.0);
    sort(note + 1,note + top + 1,cmp);
    for(int i = 1;i <= top;i++)
    {
        tp[note[i].k]++;
        ver[note[i].k][tp[note[i].k]] = note[i].ver;
        qian[note[i].k][tp[note[i].k]] = qian[note[i].k][tp[note[i].k] - 1] + note[i].gai;
    }
    rdfs(zz+1,0,0,1.0);
    
    for(int i = 0;i <= n;i++)
        printf("%.3lf\n",ans[i]);
    return 0;
}

清北學堂國慶day5解題報告