zoukankan      html  css  js  c++  java
  • 2018 “百度之星”程序设计大赛

    度度熊拼三角

     
     Accepts: 2536
     
     Submissions: 4433
     Time Limit: 2000/1000 MS (Java/Others)
     
     Memory Limit: 65536/65536 K (Java/Others)
    Problem Description

    度度熊有 NN 根木棒,每根木棒的长度为a_iai​​。

    现在要挑选其中的三根,问能拼出的三角形的最大周长是多少。

    如果不能拼成任何一个三角形,输出 -11。

    Input

    多组数据(不超过1010组),读到EOF结束。

    对于每一组数据:

    第一行一个数 NN 表示木棒数量。

    第二行一共 NN 个数,描述每一根木棒的长度。

    1 leq N leq 10001N1000

    木棒长度都是不超过100000100000的正整数

    Output

    对于每一组数据,输出一个数表示答案。

    Sample Input
    3
    1 1 100
    7
    1 9 9 90 2 2 4
    Sample Output
    -1
    22

    A最大的连续选三根

    两边之和大于第三边推广就是两小边大于大边就好了

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1005;
    int a[N];
    int main()
    {
        ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
        int n;
        while(cin>>n)
        {
            for(int i=0; i<n; i++)cin>>a[i];
            sort(a,a+n);
            int ans=-1;
            for(int i=n-3; i>=0; i--)
                if(a[i]+a[i+1]>a[i+2])
                {
                    ans=a[i]+a[i+1]+a[i+2];
                    break;
                }
            cout<<ans<<"
    ";
        }
        return 0;
    }

    本来sb的n^2logn的写法

    #include<stdio.h>
    #include<bits/stdc++.h>
    using namespace std;
    #define lson l,(l+r)/2,rt<<1
    #define rson (l+r)/2+1,r,rt<<1|1
    #define dbg(x) cout<<#x<<" = "<< (x)<< endl
    #define pb push_back
    #define fi first
    #define se second
    #define ll long long
    #define sz(x) (int)(x).size()
    #define pll pair<long long,long long>
    #define pii pair<int,int>
    #define pq priority_queue
    const int N=1e5+5,MD=1e9+7,INF=0x3f3f3f3f;
    const ll LL_INF=0x3f3f3f3f3f3f3f3f;
    const double eps=1e-9,e=exp(1),PI=acos(-1.);
    int a[N];
    int main()
    {
        ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
        int n;
        while(cin>>n)
        {
            int a[1005];
            for(int i=0; i<n; i++)cin>>a[i];
            sort(a,a+n);
            int ans=-1;
            for(int i=0;i<n;i++)
                for(int j=i+1;j<n;j++)
                {
                    int y=a[j]+a[i];
                    int pos=lower_bound(a+j+1,a+n,y)-a;
                    if(pos-1==j)continue;
                    ans=max(ans,a[i]+a[j]+a[pos-1]);
                }
            cout<<ans<<"
    ";
        }
        return 0;
    }

    度度熊学队列

     
     Accepts: 958
     
     Submissions: 5545
     Time Limit: 3000/1500 MS (Java/Others)
     
     Memory Limit: 131072/131072 K (Java/Others)
    Problem Description

    度度熊正在学习双端队列,他对其翻转和合并产生了很大的兴趣。

    初始时有 NN 个空的双端队列(编号为 11 到 NN ),你要支持度度熊的 QQ 次操作。

    1uwvalval 在编号为 uu 的队列里加入一个权值为 valval 的元素。(w=0w=0 表示加在最前面,w=1w=1 表示加在最后面)。

    2uww 询问编号为 uu 的队列里的某个元素并删除它。( w=0w=0 表示询问并操作最前面的元素,w=1w=1 表示最后面)

    3uvww 把编号为 vv 的队列“接在”编号为 uu 的队列的最后面。w=0w=0 表示顺序接(队列 vv 的开头和队列 uu 的结尾连在一起,队列vv 的结尾作为新队列的结尾), w=1w=1 表示逆序接(先将队列 vv 翻转,再顺序接在队列 uu 后面)。且该操作完成后,队列 vv 被清空。

    Input

    有多组数据。

    对于每一组数据,第一行读入两个数 NN 和 QQ。

    接下来有 QQ 行,每行 33~44 个数,意义如上。

    N leq 150000,Q leq 400000N150000,Q400000

    1 leq u,v leq N,0 leq w leq 1,1 leq val leq 1000001u,vN,0w1,1val100000

    所有数据里 QQ 的和不超过500000500000

    Output

    对于每组数据的每一个操作②,输出一行表示答案。

    注意,如果操作②的队列是空的,就输出-11且不执行删除操作。

    Sample Input
    2 10
    1 1 1 23
    1 1 0 233
    2 1 1 
    1 2 1 2333
    1 2 1 23333
    3 1 2 1
    2 2 0
    2 1 1
    2 1 0
    2 1 1
    Sample Output
    23
    -1
    2333
    233
    23333
    
    提示
    
    由于读入过大,C/C++ 选手建议使用读入优化。
    
    一个简单的例子:
    
    void read(int &x){
    	char ch = getchar();x = 0;
    	for (; ch < '0' || ch > '9'; ch = getchar());
    	for (; ch >='0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
    }

    B不卡时间,不像上次ZOJ月赛还卡时间,直接过就行了

    #include<bits/stdc++.h>
    using namespace std;
    void read(int &x)
    {
        char ch = getchar();
        x = 0;
        for (; ch < '0' || ch > '9'; ch = getchar());
        for (; ch >='0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
    }
    list<int>li[150005];
    int main()
    {
        int n,q;
        while(~scanf("%d%d",&n,&q))
        {
            for(int i=1; i<=n; i++)li[i].clear();
            for(int i=1,op,u,v,w,val; i<=q; i++)
            {
                read(op);
                switch(op)
                {
                case 1:
                {
                    read(u),read(w),read(val);
                    if(w==1)li[u].push_back(val);
                    else li[u].push_front(val);
                    break;
                }
                case 2:
                {
                    read(u),read(w);
                    if(w==1)
                    {
                        if(li[u].empty())printf("-1
    ");
                        else
                        {
                            printf("%d
    ",*li[u].rbegin()),li[u].pop_back();
                        }
                    }
                    else
                    {
                        if(li[u].empty())printf("-1
    ");
                        else printf("%d
    ",*li[u].begin()),li[u].pop_front();
                    }
                    break;
                }
                case 3:
                {
                    read(u),read(v),read(w);
                    if(w==1)li[v].reverse(),li[u].splice(li[u].end(),li[v]),li[v].clear();
                    else li[u].splice(li[u].end(),li[v]),li[v].clear();
                }
                }
            }
        }
        return 0;
    }

    度度熊剪纸条

     
     Accepts: 488
     
     Submissions: 5471
     Time Limit: 2000/1000 MS (Java/Others)
     
     Memory Limit: 65536/65536 K (Java/Others)
    Problem Description

    度度熊有一张纸条和一把剪刀。

    纸条上依次写着 NN 个数字,数字只可能是 00 或者 11。

    度度熊想在纸条上剪 KK 刀(每一刀只能剪在数字和数字之间),这样就形成了 K+1K+1 段。

    他再把这 K+1K+1 段按一定的顺序重新拼起来。

    不同的剪和接的方案,可能会得到不同的结果。

    度度熊好奇的是,前缀 11 的数量最多能是多少。

    Input

    有多组数据,读到EOF结束。

    对于每一组数据,第一行读入两个数 NN 和 KK 。

    第二行有一个长度为 NN 的字符串,依次表示初始时纸条上的 NN 个数。

    0 leq K < N leq 100000K<N10000

    所有数据 NN 的总和不超过100000100000

    Output

    对于每一组数据,输出一个数,表示可能的最大前缀 11 的数量。

    Sample Input
    5 1
    11010
    5 2
    11010
    Sample Output
    2
    3

    可以考虑在哪里下刀,肯定是在1将要开始的地方,然后头尾也是特殊的

    #include <bits/stdc++.h>
    using namespace std;
    #define fi second
    #define se first
    const int N=10005;
    int a[N],dp[N];
    char s[N];
    pair<int,int>P[N];
    int main()
    {
        ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
        int n,k;
        while(cin>>n>>k)
        {
            cin>>s;
            int tot=0;
            for(int i=0; i<N; i++)P[i].fi=P[i].se=0;
            memset(dp,0,sizeof dp);
            for(int i=0; i<n; i++)
            {
                if(s[i]=='1') P[tot].fi++;
                else tot++;
            }
            if(s[0]=='1') P[0].se=1;
            if(s[n-1]=='1') P[tot].se=1,tot++;
            if(k==0)
            {
                if(s[0]=='1')  cout<<P[0].fi<<"
    ";
                else cout<<"0
    ";
            }
            else
            {
                int sum=0;
                if(s[0]=='1') sum+=P[0].fi;
                if(s[n-1]=='1'&&tot!=1) sum+=P[tot-1].fi;
                sort(P,P+tot,greater<pair<int,int> >());
                int pos=0;
                while(P[pos].se&&tot<n)pos++;
                P[pos].se=1;
                for(int j=0; j<tot; j++)
                {
                    for(int i=k; i>1; i--)dp[i]=max(dp[i],dp[i-2+P[j].se]+P[j].fi);
                    if(P[j].se==1)dp[1]=max(dp[1],dp[0]+P[j].fi);
                }
                cout<<max(sum,dp[k])<<"
    ";
            }
        }
        return 0;
    }

    还有一种写法

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 10005;
    int n, k, f[maxn];
    
    
    string s;
    int solve() 
    {
      vector<pair<int, int>> vec;
      int p = 0;
      while(p < n) 
      {
        if(s[p] == '1') 
        {
          int j = p, tot = 0;
          while(j < n && s[j] == '1') 
          {
            tot++, j++;
          }
          if(p == 0) 
            vec.push_back(make_pair(tot, 1));
          else if(j == n) 
            vec.push_back(make_pair(tot, 1));
          else 
            vec.push_back(make_pair(tot, 2));
          p = j;
        }
        else p++;
      }
      if(k == 1) 
      {
        if(s[0] == '1') 
          return vec[0].first;
        return 0;
      }
      memset(f, 0, sizeof(f));
      for(int i = 0; i < vec.size(); i++) 
        for(int j = k; j >= vec[i].second; j--) 
          f[j] = max(f[j], f[j-vec[i].second]+vec[i].first);
      return f[k];
    }
    int main() 
    {
      while(cin >> n >> k) 
      {
        cin >> s;k++;
        cout << solve() << endl;
      }
    }

    度度熊看球赛

     
     Accepts: 120
     
     Submissions: 491
     Time Limit: 2000/1000 MS (Java/Others)
     
     Memory Limit: 65536/65536 K (Java/Others)
    Problem Description

    世界杯正如火如荼地开展!度度熊来到了一家酒吧。

    有 NN 对情侣相约一起看世界杯,荧幕前正好有 2 imes N2×N 个横排的位置。

    所有人都会随机坐在某个位置上。

    当然,如果某一对情侣正好挨着坐,他们就会有说不完的话,影响世界杯的观看。

    一般地,对于一个就座方案,如果正好有 KK 对情侣正好是挨着坐的,就会产生 D^KDK​​ 的喧闹值。

    度度熊想知道随机就座方案的期望喧闹值。

    为了避免输出实数,设答案为 ansans,请输出 ans imes (2N)!ans×(2N)modmoPP 的值。其中 P=998244353P=998244353

    Input

    有多组数据(不超过 10001000 组),读到EOF结束。

    对于每一组数据,读入两个数 NN 和 DD 。

    1 leq N,D leq 10001N,D1000

    Output

    对于每一组数据,输出一个数表示答案。

    Sample Input
    1 10
    2 3
    Sample Output
    20
    104

    读错题,竟然是一排有2*n个座位,然后找到递推式就好了

    #include<bits/stdc++.h>
    using namespace std;
    int dp[1005][1005],C[2005][2005];
    const int MD=998244353;
    int main()
    {
        int i,j;
        for (i=0; i<2005; i++)
        {
            C[i][0]=1;
            for (j=1; j<=i; j++)
                C[i][j]=(C[i-1][j-1]+C[i-1][j])%MD;
        }
        dp[0][0]=1;
        for(i=1; i<1005; i++) //2i个位置 j个相邻
        {
            for (j=0; j<i; j++)
            {
                if(dp[i-1][j]==0)continue;
                int t=(i-1)*2-j+1;//不会造成影响
                dp[i][j+1]=(dp[i][j+1]+2LL*dp[i-1][j]*C[t][1]%MD)%MD;//组1
                dp[i][j]=(dp[i][j]+2LL*dp[i-1][j]*C[t][2]%MD)%MD;//没有贡献
                if(j>0)dp[i][j-1]=(dp[i][j-1]+2LL*dp[i-1][j]*C[t][1]%MD*C[j][1]%MD)%MD;//拆1
                if(j>1)dp[i][j-2]=(dp[i][j-2]+2LL*dp[i-1][j]*C[j][2]%MD)%MD;//拆2
                dp[i][j]=(dp[i][j]+2LL*dp[i-1][j]*C[j][1]%MD)%MD;//拆1+组1
            }
        }
        int n,K;
        while (~scanf("%d%d",&n,&K))
        {
            int ans=0,t=1;
            for(i=0; i<=n; i++)ans=(ans+1LL*t*dp[n][i])%MD,t=1LL*t*K%MD;
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    openldap
    Java实现 洛谷 P1200 [USACO1.1]你的飞碟在这儿Your Ride Is He…
    Java实现 洛谷 P1200 [USACO1.1]你的飞碟在这儿Your Ride Is He…
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P1567 统计天数
    Java实现 洛谷 P1567 统计天数
  • 原文地址:https://www.cnblogs.com/BobHuang/p/9501180.html
Copyright © 2011-2022 走看看