清北学堂国庆day5解题报告

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了清北学堂国庆day5解题报告相关的知识,希望对你有一定的参考价值。

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解题报告的主要内容,如果未能解决你的问题,请参考以下文章

清北学堂国庆day1解题报告

清北学堂国庆day6解题报告

清北学堂国庆day7解题报告

清北学堂国庆day3解题报告

清北学堂国庆day4解题报告

2017.7.21夏令营清北学堂解题报告