zoukankan      html  css  js  c++  java
  • 2016 icpc ECfinal && codeforcesgym101194

    一不小心惨变旅游队,不过上海的风景不错

    顺带找其他队交流一下集训经验。。。或许可以成为选拔和集训16级的依据

    A、直接模3就可以了,2^(3*n)%7=1

    C、Mr. Panda and Strips

    由于只求1条或2条,n<=1000,支持o(n2)解法,可以区间DP出单段区间含不重复数字的链

    由于包含同数字之间的区间肯定不能用,左区间的最右数字肯定就是筛选目标

    可以利用这个性质,枚举左区间,左区间从左到右,之后右区间从左到右

    可以在扫描右区间碰到已存在数字时直接换左区间

    没有碰到就把区间[1,n]按照最右数字在不同位置的存在情况切区间,把包含右数字的取出,剩下的区间在最后取最大结果

    由于不包含某个数字的区间肯定在上一轮被取过,初始放进集合的区间可随左区间缩小,可以防止重复取答案

    此代码为virtual judge的某位大侠原创,我只是为了适应vc6.0和改进一个小地方把代码改得不像样而已。。。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <set>
    #include <vector>
    #include <iterator>
    using namespace std;
    typedef pair<int,int> PII;
    const int N=1005,MAX=100005;
    vector<int> p[MAX];
    int a[N],dp[N][N];
    bool isok[N][N];
    int vis[MAX];
    set<PII> ival;
    multiset<int> q;
    int max(int a,int b){return a>b?a:b;}
    void split(int x)//查出x属于的[a,b],把[a,b]切成[a,x-1]和[x+1,b]
    {
        set<PII>::iterator it=ival.lower_bound(PII(x+1,0));
        if (it==ival.begin()) return;
        it--;
        int a=it->first,b=it->second;
        ival.erase(it);
        q.erase(q.find(dp[a][b]));
        if (a<x) {
            ival.insert(PII(a,x-1));
            q.insert(dp[a][x-1]);
        }
        if (x<b) {
            ival.insert(PII(x+1,b));
            q.insert(dp[x+1][b]);
        }
    }
    
    int main()
    {
        int T,n,i;
        scanf("%d",&T);
        for (int t=1;t<=T;t++) {
            scanf("%d",&n);
            memset(vis,0,sizeof(vis));
            for (i=1;i<MAX;i++) {
                p[i].clear();
            }
            for (i=1;i<=n;i++) {
                scanf("%d",&a[i]);
                p[a[i]].push_back(i);
            }
            //从左区间延伸到不可延伸的地方
            for (i=1;i<=n;i++) {
                bool f=true;
                for (int j=i;j<=n;j++) {
                    if (vis[a[j]]==i) {
                        f=false;
                    }
                    vis[a[j]]=i;
                    isok[i][j]=f;
                }
            }
            //区间DP
            for (int len=1;len<=n;len++) {
                for (int i=1;i+len-1<=n;i++) {
                    int j=i+len-1;
                    if (isok[i][j]) {
                        dp[i][j]=j-i+1;
                    } else {
                        dp[i][j]=max(dp[i+1][j],dp[i][j-1]);
                    }
                }
            }
            int ans=-1;
            memset(vis,0,sizeof(vis));
            //vis储存时间戳,比储存bool然后o(n*n)全设假高效
            for (i=1;i<=n;i++) {
                ival.clear();q.clear();
                ival.insert(PII(i,n));//根据左区间的限制确定查询区间
                q.insert(dp[i][n]);
                for (int j=i;j<=n;j++) {
                    if (vis[a[j]]==i) {
                        break;
                    }
                    vis[a[j]]=i;//根据对应数字所在位置切分区间
                    for (int k=0;k<p[a[j]].size();k++) {
                        split(p[a[j]][k]);
                    }
                    int cur=j-i+1;
                    if (!q.empty()) {
                        cur+=*q.rbegin();//取出最大
                    }
                    ans=max(cur,ans);
                }
            }
            printf("Case #%d: %d
    ",t,ans);
        }
        return 0;
    }
    View Code

    D、刚开始贪心炸了,后来发现要二分,然而应该是中间处理写崩了。。。

    E、Bet

    题目意思场上没有读出。。。给出每个队的赔率Ai:Bi,按照一定比例投注每个队,要求在尽量投多队的同时,任何投的队赢都能赚(就是这里想不明白!!!为什么没有投的队就一定不会赢)获得金是本金*(ai+bi)/ai

    设投在i队的本金是ci,总投注d,则整个题目就是说选出尽可能多的i并且所有的c加起来就是d,而且所有i都满足ci*(ai+bi)/ai>d

    那投在i队的比例就是qi=ci/d

    本质上就是求使得i集合全部满足qi>ai/(ai+bi),q1+q2+...+qn=1时,i的数量最多

    太简单了,把qi等同于ai/(ai+bi),然后排序,从小到大逐一加,加到大于1时停止计数

    然鹅----这个算式没有高精度会炸。本来想写一波高精除法,结果看到有人用long double硬杠过去就脱力了。。。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    
    int n;
    long double al[105],res;
    double k,u;
    int main()
    {
        int t,cas,i,ik,iu;
        scanf("%d",&cas);
        for(t=1;t<=cas;t++)
        {
            scanf("%d",&n);
            for(i=0;i<n;i++)
            {
                scanf("%lf:%lf",&k,&u);
                ik=floor(k*1000),iu=floor(u*1000);
                al[i]=1.0*ik/(ik+iu);
            }
            sort(al,al+n);
                    int cnt=0;
            for(i=0,res=0;i<n;i++)
                    {
                    res+=al[i];
                    if(res>=1)break;
                    cnt++;
                    }
            printf("Case #%d: %d
    ",t,cnt);
        }
        return 0;
    }
    View Code

    H、Great Cells

    设gn是同行同列极大值至少有n个的方案数,

    答案公式a0+2a1+3a2+...+(n+1)an=(a0+a1+...+an)+1a1+2a2+3a3+...+nan

    发现整道题目其实是求所有情况的方案数+这些情况里面极大值的总个数

    而极大值的个数可以每个格子单独算,就是每个格子对答案的贡献

    然后除了n==1 && m==1这种是里面取啥值都是极大值

    其他的不是1才是极大值,而且同行同列都要小于本格

    ans=连加(i=2~k)(i-1)^(n-1+m-1)*k^[(n-1)*(m-1)] //前者是与此格同行同列的格子个数,受数字i制约;后者是被划出的可任意填的格子个数

    得到单个格子极大值个数

    然后k^(n*m)+ans*n*m //所有情况的方案数+所有格子对答案的贡献

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #include<queue>
    #include<stack>
    #include<math.h>
    #include<vector>
    #include<map>
    #include<set>
    #include<stdlib.h>
    #include<cmath>
    #include<string>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    typedef pair<int,int> pii;
    #define X first
    #define Y second
    typedef __int64 ll;
    int max(int a,int b){return a>b?a:b;}
    const int MOD=1000000007;
    
    ll powMod(ll b,ll t,ll m)
    {
        ll res=1;
        while(t)
        {
            if(t&1)res=res*b%m;
            b=b*b%m;
            t>>=1;
        }
        return res;
    }
    
    int main()
    {
        int i,cas,n,m,k;
        scanf("%d",&cas);
        for(int t=1;t<=cas;t++)
        {
            scanf("%d%d%d",&n,&m,&k);
            printf("Case #%d: ",t);
            ll res=0;
            if(n==1 && m==1)res++;//只有1个格时填1也是极大值
            for(i=2;i<=k;i++)//每个数取i时使此数为极大值的方案数
            {
                res=(powMod(i-1,n-1+m-1,MOD)*powMod(k,(n-1)*(m-1),MOD)+res)%MOD;
            }
            res=(res*n*m)%MOD;//每个格子可能变成极大值的方案数乘总格数
            res+=powMod(k,n*m,MOD);//没有限制的方案数
            printf("%I64d
    ",res%MOD);
        }
        return 0;
    }
    View Code

    L、每场比赛3种情况,穷举就可以了

  • 相关阅读:
    Bootsrap 的 Carousel
    Bootstrap 的 Tooltip 和 Popover
    JavaScript 继承
    Bootstrap 的 Collapse
    Bootstrap 组件之 Panel
    Bootstrap 组件之 List group
    Bootstrap 组件之 Nav
    使用 classList API
    Bootstrap 的 Dropdown
    Bootstrap 的 Modal
  • 原文地址:https://www.cnblogs.com/dgutfly/p/6171396.html
Copyright © 2011-2022 走看看