zoukankan      html  css  js  c++  java
  • UVA写题记录

    UVA写题记录

    UVA 1451

    Description

    求一个长度为N的01串长度至少为L的子串的数字平均值最大的起点和终点

    Solution

    可以看成斜率来做

    但我写的二分,二分平均值然后扫一遍就行了

    O(nlogn)

    #include<bits/stdc++.h>
    
    using namespace std;
    
    inline int read()
    {
        int f = 1,x = 0;
        char ch;
        do
        {
            ch = getchar();
            if(ch == '-') f = -1;
        }while(ch < '0'|| ch > '9');
        do
        {
            x = (x<<3) + (x<<1) + ch - '0';
            ch = getchar();
        }while(ch >= '0'&&ch <= '9');
        return f*x;
    } 
    
    #define eps 1e-6
    const int MAXN = 100000 + 10;
    
    int T,pos;
    int ans1,ans2;
    int n,L;
    char a[MAXN];
    double sum[MAXN];
    
    inline bool check(double x)
    {
        for(int i=1;i<=n;i++) sum[i] = sum[i-1] + a[i-1] - '0' - x;
        double minn = 0,maxx = -200000.0;
        for(int i=L;i<=n;i++)
        {
            if(minn >= sum[i-L]) minn = sum[i-L],pos=i-L+1;
            if(sum[i]-minn>maxx + eps)
            {
                maxx = sum[i] - minn;
                ans1 = pos;
                ans2 = i;
            }
        }
        if(maxx + eps > 0) return 1;
        return 0;
    }
    
    int main()
    {
        T = read();
        while(T--)
        {
            n = read(),L = read();
            scanf("%s",a);
            double l = 0.0 ,r = 1.0;
            for(int i=1;i<=100;i++)
            {
                double mid = (r+l)/2.0;
                if(check(mid)) l = mid;
                else r = mid;
            }
        //    check(l+eps);
            printf("%d %d
    ",ans1,ans2);
        }
    }
    View Code

     UVA 1437

    Description

    给定两个长度相等且只有小写字母组成的字符串S,T
    每步把S的连续子串变成相同的字母
    至少需要多少步可以让S变成T

    Solution

    普及组难度DP

    考虑一个空串至少要刷几次能到B串

    一个显然的区间DP

    然后再考虑A串来刷

    另  $ DP_i $  表示A串前I个字母需要刷多少次能和B匹配

    显然如果相同位一样可以选择不刷

    #include<bits/stdc++.h>
    
    using namespace std;
    
    inline int read()
    {
        int f = 1,x = 0;
        char ch;
        do
        {
            ch = getchar();
            if(ch == '-') f = -1;
        }while(ch < '0'|| ch > '9');
        do
        {
            x = (x<<3) + (x<<1) + ch - '0';
            ch = getchar();
        }while(ch >= '0'&&ch <= '9');
        return f*x;
    } 
    
    const int MAXN = 200 + 10;
    
    char a[MAXN],b[MAXN];
    int f[MAXN][MAXN];
    int dp[MAXN];
    
    int main()
    {
        while(~scanf("%s%s",a+1,b+1))
        {
            int len = strlen(a+1);
            memset(f,0,sizeof(f));
            for(int i=0;i<=len;i++) f[i][i] = 1;
            for(int l=2;l<=len;l++)
            {
                for(int i=1;i+l-1<=len;i++)
                {
                    int j = i + l - 1;
                    f[i][j] = min(f[i][j-1],f[i+1][j]) + !(b[i]==b[j]);
                    for(int k=i+1;k<j;k++) f[i][j] = min(f[i][j],f[i][k]+f[k+1][j]);
                }
            }
            memset(dp,0,sizeof(dp));
            for(int i=1;i<=len;i++) dp[i] = f[1][i];
            for(int i=1;i<=len;i++)
            {
                if(a[i]==b[i]) dp[i] = dp[i-1];
                else
                {
                    for(int j=1;j<i;j++) dp[i] = min(dp[i],dp[j]+f[j+1][i]);
                }
            }
            printf("%d
    ",dp[len]);
        }
    }
    View Code

    UVA 11136

    Description

    提供一个支持插入,查询和删除最大值最小值的数据结构

    Solution

    直接mutiset

    #include<bits/stdc++.h>
    
    using namespace std;
    
    inline int read()
    {
        int f = 1,x = 0;
        char ch;
        do
        {
            ch = getchar();
            if(ch == '-') f = -1;
        }while(ch < '0'|| ch > '9');
        do
        {
            x = (x<<3) + (x<<1) + ch - '0';
            ch = getchar();
        }while(ch >= '0'&&ch <= '9');
        return f*x;
    } 
    
    int n;
    
    int main()
    {
        while(~scanf("%d",&n))
        {
            if(!n) return 0;
            long long ans = 0;
            multiset<int>s;
            for(int i=1;i<=n;i++)
            {
                int k = read();
                for(int i=1;i<=k;i++)
                {
                    int a = read();
                    s.insert(a);
                }    
                ans += *s.rbegin() - *s.begin();
                s.erase(s.begin());s.erase(s.find(*s.rbegin()));
            }
            printf("%lld
    ",ans);
            
        }
    }
    View Code

    UVA 1639

    Description

    有两个盒子各有n (n<=2e5) 个糖,每天随机选一个(概率分别为p,1-p),然后吃一颗糖。直到有一天,打开盒子一看,没糖了!输入n,p,求此时另一个盒子里糖的个数的数学期望。

    Solution

    假设没糖的是第一个盒子,那么第一个盒子拿了n+1次,第二个盒子拿了0次到n次,我们可以假设第二个盒子最终剩了i颗糖,这个时候概率显然就是

    $ inom{2n-i}{n} p^{n+1} imes  (1-p)^{n-i}  $

    但这道题真正的考点其实是在精度上,可以看出这个式子算出来的值是很小的,无法保证精度

    所以取个对数就可以了

    #include<bits/stdc++.h>
    
    using namespace std;
    
    inline int read()
    {
        int f = 1,x = 0;
        char ch;
        do
        {
            ch = getchar();
            if(ch == '-') f = -1;
        }while(ch < '0'|| ch > '9');
        do
        {
            x = (x<<3) + (x<<1) + ch - '0';
            ch = getchar();
        }while(ch >= '0'&&ch <= '9');
        return f*x;
    } 
    
    const int MAXN = 2e5 + 10;
    
    long double L[(MAXN<<1)+5];
    int n;
    double p;
    int C=0;
    
    int main()
    {
        for(int i=1;i<=(MAXN<<1);i++) L[i] = L[i-1] + log(i);
        while(~scanf("%d%lf",&n,&p))
        {
            double ans = 0.0;
            for(int i=1;i<=n;i++)
            {
                long double res1 = L[2*n-i]-L[n]-L[n-i];
                long double res2 = res1 + log(p)*(n+1) + log(1-p)*(n-i);
                long double res3 = res1 + log(1-p)*(n+1) + log(p)*(n-i);
                ans += i * (exp(res2)+exp(res3));  
            }
            printf("Case %d: %.6lf
    ",++C,ans);
        }
    }

    UVA 11971

    Description

    在直线上随机取k个点,分成的k+1段拼起来能组成多边形的概率

    Solutuon

    能组成多边形的条件是最大边要小于其他边之和

    于是可以知道最大边长度要小于n/2

    就像CSPd2t1一样从反面考虑,当不能组成多边形时大于n/2的边只能有一条

    我们先假设最长边以左边为起点,于是剩下的点都只能在中点往右才不能组成多边形,此时概率为 $ frac{1}{2^{k}} $

    且对于每种情况,最长边可以向右平移,一共有k+1种放法

    所以答案就是 $ 1-(k+1) imes frac{1}{2^{k}}  $

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define LL long long
    
    inline LL read()
    {
        LL f = 1,x = 0;
        char ch;
        do
        {
            ch = getchar();
            if(ch == '-') f = -1;
        }while(ch < '0'|| ch > '9');
        do
        {
            x = (x<<3) + (x<<1) + ch - '0';
            ch = getchar();
        }while(ch >= '0'&&ch <= '9');
        return f*x;
    } 
    
    inline LL Pow(LL a, LL b)
    {
        LL ans = 1,mul = a;
        while(b)
        {
            if(b&1) ans = ans * mul;
            mul = mul * mul;
            b>>=1;
        }
        return ans;
    }
    
    inline LL gcd(LL a ,LL b)
    {
        if(!b) return a;
        return gcd(b,a%b);
    }
    
    LL T;
    LL n,k;
    
    int main()
    {
        int kase = 0;
        T = read();
        while(T--)
        {
            ++kase;
            n = read(),k = read();
            LL fz = Pow(2,k)-k-1;
            LL fm = Pow(2,k);
            LL ys = gcd(fz,fm);
            fm/=ys,fz/=ys;
            printf("Case #%d: %lld/%lld
    ",kase,fz,fm);
        }
    }

    UVA1363

    Description

    给你n和k,
    计算
    for(int i=1;i<=n;i++) ans+=k%i;
    输出ans
    n,k∈[1,10^9]

    Solution

    简单的整除分块

    和一道远古省选题一样

    #include<bits/stdc++.h>
    
    using namespace std;
    
    inline long long read()
    {
        long long f=1,x=0;
        char ch;
        do
        {
            ch=getchar();
            if(ch=='-');
        }while(ch<'0'||ch>'9');
        do
        {
            x=(x<<3)+(x<<1)+ch-'0';
            ch=getchar();
        }while(ch>='0'&&ch<='9');
        return f*x;
    } 
    
    long long n,k;
    
    int main()
    {
        while(scanf("%lld%lld",&n,&k)==2)
        {
            long long ans=n*k;
            long long r=0;
            for(long long l=1;l<=n;l=r+1)
            {
                if(k/l!=0) r=min(k/(k/l),n);
                else r=n;
                ans-=(r-l+1)*(k/l)*(r+l)/2;
            }
            cout<<ans<<endl;
        }
    }

    UVA11895

    Description

    在一次抽奖活动中,有n个抽奖箱。第i个抽奖箱有ti个信封,其中li个信封里面有奖。所有人排队抽奖,每次抽完奖都把信封丢回原来的箱子里。每个人都知道上述数据,都很聪明,但是并不知道前面的人中奖没有。求第k个人中奖的概率。

    Solution

    大水题

    拿个优先队列动态维护一波最优概率即可

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define LL long long
    
    inline LL read()
    {
        LL f = 1,x = 0;
        char ch;
        do
        {
            ch = getchar();
            if(ch == '-') f = -1;
        }while(ch < '0'||ch > '9');
        do
        {
            x = (x<<3) + (x<<1) + ch - '0';
            ch = getchar();
        }while(ch >= '0'&&ch <= '9');
        return f*x;
    }
    
    inline LL gcd(LL a,LL b)
    {
        if(!b) return a;
        else return gcd(b,a%b);
    }
    
    int T;
    LL n,k;
    
    struct node
    {
        LL p,q,t;
        friend bool operator < (node a1,node a2)
        {
            return a1.p * a2.q < a2.p * a1.q;
        }
    };
    
    priority_queue<node>pq;
    
    int main()
    {
        T = read();
        while(T--)
        {
            n = read();k = read();
            for(int i=1;i<=n;i++) 
            {
                LL t = read(),l = read();
                LL ys = gcd(t,l);
                node a;
                a.p = l/ys;a.q = t/ys;a.t = t;
                pq.push(a);
            }    
            for(int i=1;i<k;i++)
            {
                node u = pq.top();
                pq.pop();
                u.p *= (u.t - 1);
                u.q *= u.t;
                LL ys = gcd(u.p,u.q);
                u.p/=ys;u.q/=ys;
                pq.push(u);
            }
            printf("%lld/%lld
    ",pq.top().p,pq.top().q);
            while(pq.size()) pq.pop();
        }
    }
  • 相关阅读:
    开发周记
    开发日记03
    开发日记01
    MVC实例应用
    MVC概述
    23种设计模式简述
    xx系统属性分析
    淘宝网质量属性
    架构漫谈阅读笔记
    浅谈软件架构师工作流程
  • 原文地址:https://www.cnblogs.com/wlzs1432/p/13435408.html
Copyright © 2011-2022 走看看