zoukankan      html  css  js  c++  java
  • EZ 2017 01 07 t

      这名字诡异(然而就是这样)

      这次主要是yekehe和yu‘ao都来了,所以很开心的讨论(上了200)。

      但是,yu’ao dalao又AK了!(666666)

      不过总体难度也不高,主要是T3没思路。

      T1 二分或桶

      ·如果你不会这道题,出门右转找傅哥去。

      去年蒟蒻时期的噩梦啊。然而只是一道PJ的水题。

      二分洪水的高度(题目错了,数据是向上取整),然后判断是否可行。

      注意开long long(不开80)

      CODE

    #include<cstdio>
    using namespace std;
    typedef long long LL;
    const int N=405;
    LL a[N][N],n,m,i,j,v,h,s;
    inline char get(void) 
    {
        static char buf[100000], *p1 = buf, *p2 = buf;
        if (p1 == p2) 
        {
            p2 = (p1 = buf) + fread(buf, 1, 100000, stdin);
            if (p1 == p2) return EOF;
        }
        return *p1++;
    }
    inline void read(LL &x) 
    {
        x = 0; static char c;
        for (; !(c >= '0' && c <= '9'); c = get());
        for (; c >= '0' && c <= '9'; x = x * 10 + c - '0', c = get());
    }
    inline bool check(LL k)
    {
        long long res=0;
        for (i=1;i<=n;++i)
        for (j=1;j<=m;++j)
        if (a[i][j]<=k)
        res+=k-a[i][j];
        return res<v;
    }
    int main()
    {
        freopen("water.in","r",stdin); freopen("water.out","w",stdout);
        read(n); read(m); read(v);
        for (i=1;i<=n;++i)
        for (j=1;j<=m;++j)
        read(a[i][j]);
        LL l=0,r=v+1;
        while (l<=r)
        {
            LL mid=l+r>>1;
            if (check(mid)) h=mid+1,l=mid+1; else r=mid-1;
        }
        for (i=1;i<=n;++i)
        for (j=1;j<=m;++j)
        if (a[i][j]<=h) s+=a[i][j];
        printf("%lld %lld",h,s);
        return 0;
    }

      T2 前缀和+姜度大佬玄学算法。

      首先思路很好想,把墙的高度都减去一个x就转化成了一个找连续区间的和>=0的问题了。

      暴力:O(n^3); 前缀和优化:O(n^2); 单调栈上二分(裸二分会炸):O(n log n);

      这些,都过不了。

      然后由于姜度dalao暑假来HW给我们讲过了求最长的区间和>=k的算法,非常简洁且有效率(O(n));

      设一个数组mx[]表示后向前缀和最大值,当前答案为res,那么如果mx[i+res]>=s[i],则向后枚举答案一定增大。

      由于两个指针(i和res)一起增大,所以复杂度为O(n);

      CODE

    #include<cstdio>
    //#include<ctime>
    using namespace std;
    typedef long long LL;
    const LL N=1000005;
    LL sum[N],a[N],mx[N],n,m,i,x,res;
    inline char get(void) 
    {
        static char buf[10000000], *p1 = buf, *p2 = buf;
        if (p1 == p2) 
        {
            p2 = (p1 = buf) + fread(buf, 1, 10000000, stdin);
            if (p1 == p2) return EOF;
        }
        return *p1++;
    }
    inline void read(LL &x) 
    {
        x = 0; static char c;
        for (; !(c >= '0' && c <= '9'); c = get());
        for (; c >= '0' && c <= '9'; x = x * 10 + c - '0', c = get());
    }
    inline void write(LL x)
    {
        if (x/10) write(x/10);
        putchar(x%10+'0');
    }
    int main()
    {
        freopen("dam.in","r",stdin); freopen("dam.out","w",stdout);
        read(n); read(m);
        for (i=1;i<=n;++i)
        read(a[i]);
        while (m--)
        {
            read(x);
            sum[0]=0;
            for (i=1;i<=n;++i)
            sum[i]=sum[i-1]+a[i]-x;
            mx[n]=sum[n];
            for (i=n-1;i;--i)
            mx[i]=sum[i]>mx[i+1]?sum[i]:mx[i+1];
            res=0;
            for (i=1;i+res<=n;++i)
            while (mx[i+res]>=sum[i-1]&&i+res<=n) ++res;
            write(res);
            putchar(' ');
        }
        //printf("
    %.2lf",(double)clock());
        return 0;
    }

      T3 当时看到题目蒙蔽了,从来没坐过概率之类的问题。

      yu‘ao dalao打了很长(貌似)的递推,然后我看了标算才大彻大悟。

      这就是一道你知道概率公式记忆化搜索的题。

      把一个状态(m,a[])(m是剩下的天数,a[]是每个人剩下的体力)hash成一个不会重复的大整数。记搜即可。

      CODE

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    using namespace std;
    const int N=5,seed=51,MAX_SIZE=20000005;
    int a[N],n,m,i;
    double s[MAX_SIZE];
    bool f[MAX_SIZE];
    inline void read(int &x)
    {
        x=0; char ch=getchar();
        while (ch<'0'||ch>'9') ch=getchar();
        while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    }
    inline int hash(int m)
    {
        int res=m;
        for (int i=1;i<n;++i)
        res=res*seed+a[i];
        return res;
    }
    inline double dfs(int m)
    {
        if (!m) return 1.0*(a[1]>0);
        if (f[hash(m)]) return s[hash(m)];
        f[hash(m)]=1;
        double tot=0.0,t=0.0;
        for (int i=1;i<=n;++i)
        if (a[i]>0)
        {
            a[i]--; tot+=dfs(m-1); a[i]++; t++;
        }
        if (t) return s[hash(m)]=tot/t; else return 0;
    }
    int main()
    {
        freopen("hung.in","r",stdin); freopen("hung.out","w",stdout);
        read(n); read(m);
        for (i=1;i<=n;++i)
        read(a[i]);
        for (i=1;i<=n;++i)
        {
            swap(a[1],a[i]); 
            memset(f,0,sizeof(f));
            printf("%.6lf
    ",dfs(m));
        }
        return 0;
    }
  • 相关阅读:
    C# 0xC0000005 捕获
    “Task”未包含“Run”的定义
    Win10 清理自带APP
    SQLServer 2014 内存优化表
    PHP 常用函数
    Android开发之旅:环境搭建及HelloWorld
    C# PropertyGrid控件应用心得
    SQL Server 连接池 (ADO.NET) MSDN
    查看数据库连接池函数
    WCF客户端调用服务器端错误:"服务器已拒绝客户端凭据"。
  • 原文地址:https://www.cnblogs.com/cjjsb/p/8270366.html
Copyright © 2011-2022 走看看