zoukankan      html  css  js  c++  java
  • 第十周周赛题解

    A题:

    二分题目,具体二分公式看我代码吧(ーー゛)

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstring>
     5 #define maxa 20100
     6 using namespace std;
     7 int a[maxa],l[maxa],r[maxa],n;
     8 bool comp(int p)
     9 {
    10     int x= a[1],y= p-a[1],i;
    11     memset(l,0,sizeof(l));
    12     memset(r,0,sizeof(r));
    13     l[1] =x;
    14     r[1] = 0;
    15     for(i=2; i<=n; ++i)
    16     {
    17         if(i%2==0)
    18         {
    19             l[i] = min(x-l[i-1],a[i]);
    20             r[i] =a[i]-l[i];
    21         }
    22         else
    23         {
    24             r[i] = min(y-r[i-1],a[i]);
    25             l[i] = a[i]-r[i];
    26         }
    27     }
    28     return l[n]==0;
    29 }
    30 int main()
    31 {
    32     int i;
    33     //freopen("E:/造数据/in1_test.in","r",stdin);
    34     //freopen("E:/造数据/in1_test.out","w",stdout);
    35     while(scanf("%d",&n)!=EOF)
    36     {
    37         for(i=1; i<=n; ++i)
    38             scanf("%d",&(a[i]));
    39         int L=0,R=0;
    40         for(i=1; i<n; ++i)
    41         {
    42             L = max(L,a[i]+a[i+1]);
    43             R = max(R,3*a[i]);
    44         }
    45         R =max(R,3*a[n]);
    46         L = max(L,a[1]+a[n]);
    47         if(n%2==1)
    48         {
    49             while(L<=R)
    50             {
    51                 int mid =(L+R)/2;
    52                 if(comp(mid)==true)
    53                 {
    54                     R =mid-1;
    55                 }
    56                 else
    57                     L = mid+1;
    58             }
    59         }
    60         printf("%d
    ",L);
    61     }
    62     return 0;
    63 }
    View Code

    B题:

    topo排序然后简单dp,或者直接爆搜加个记忆化...(如果是记忆化,记得不要用0来表示未访问的点QwQ)

     1 #include <stdio.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int MAXN=1e5+5, MD=10007;
     5 int in[MAXN], deg[MAXN], to[MAXN][10], K[MAXN], N;
     6 int p[MAXN], M, f[MAXN], ans;
     7 int read()
     8 {
     9     int r=0,c=getchar();
    10     while(c<'0'||'9'<c)
    11         c=getchar();
    12     while('0'<=c&&c<='9')
    13         r=r*10+c-'0', c=getchar();
    14     return r;
    15 }
    16 int main()
    17 {
    18     scanf("%d", &N);
    19     for(int i=1; i<=N; ++i)
    20     {
    21         K[i]=read();
    22         for(int j=0; j<K[i]; ++j)
    23             in[to[i][j]=read()]++;
    24     }
    25     for(int i=1; i<=N; ++i)
    26         if(!in[i])
    27             f[p[M++]=i]=1;
    28     for(int i=0; i<M; ++i)
    29     {
    30         int u=p[i];
    31         for(int j=0; j<K[u]; ++j)
    32         {
    33             int v=to[u][j];
    34             if(!(--in[v]))
    35                 p[M++]=v;
    36         }
    37     }
    38     for(int i=0; i<M; ++i)
    39     {
    40         int u=p[i];
    41         for(int j=0; j<K[u]; ++j)
    42         {
    43             int v=to[u][j];
    44             f[v]=(f[v]+f[u])%MD;
    45         }
    46         if(!K[u])
    47             ans=(ans+f[u])%MD;
    48     }
    49     printf("%d
    ", ans);
    50     return 0;
    51 }
    View Code

    C题:

    这是一道数学题(ーー゛)

    题意:已知T

    积化和差公式推一下即可。最后枚举T

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 using namespace std;
     5 long long n;
     6 int i,t;
     7 long double p,dt=1e9,s,ds;
     8 int main()
     9 {
    10     scanf("%lld%Lf",&n,&p);
    11     for(i=1; i<68; i++)
    12     {
    13         s=(cos(i-0.5)-cos(i+n-0.5))/sin(0.5)/2;
    14         ds=abs(s-p);
    15         if(ds<dt)
    16         {
    17             t=i;
    18             dt=ds;
    19         };
    20     }
    21     printf("%d",t);
    22 }
    View Code

    D题:

    区间DP题目

    状态只有2种:从左边拿和从右边拿。

    假设当前状态a1,a2,a3,a4,a5,如果第一个人选最左边的,则问题转化为四个数a2,a3,a4,a5,然后第二个人先选,由于题目说第二个人方案也最优,所以选的也是最优方案,即f[i+1][j];先选右边同理。

    f[i][j]表示i~j区间段第一个人选的最优方案。

    所以dp转移方程为:f[i][j]=max{ sum[i+1][j]-f[i+1][j]+ai,sum[i][j-1]-f[i][j-1]+aj }

    sum[i][j]其实就等于sum[1][j]-sum[1][i-1],于是我们用一个s数组,s[i]表示前1~i个数的和,就好了。

    所以dp转移方程也可写成f[i][j]=max((s[j]-s[i-1])-f[i+1][j],(s[j]-s[i-1])-f[i][j-1]);

    根据dp转移方程我们可以发现,要得到状态f[i][j],必须要得到状态f[i+1][j]和f[i][j-1]。

     1 #include<stdio.h>
     2 #include<algorithm>
     3 using namespace std;
     4 int n,i,j;
     5 int a[101];//存数
     6 int f[101][101];
     7 //f[i][j]表示取i~j这个区间段player1最高得分
     8 int s[101];//s[i]表示a[1]~a[i]的和
     9 int main()
    10 {
    11     //freopen("E:/造数据/in2_test.in","r",stdin);
    12     //freopen("E:/造数据/in2_test.out","w",stdout);
    13     while(scanf("%d",&n)!=EOF)
    14     {
    15         for (i=1; i<=n; i++)
    16         {
    17             scanf("%d",&a[i]);//读入 s
    18             s[i]=s[i-1]+a[i];//求和
    19             f[i][i]=a[i];//初始化
    20         }
    21         //表示a[i]~a[j]的和的方法:s[j]-s[i-1]
    22         for (i=n-1; i>=1; i--)
    23             for (j=i+1; j<=n; j++)
    24                 f[i][j]=max((s[j]-s[i-1])-f[i+1][j],
    25                             (s[j]-s[i-1])-f[i][j-1]);
    26         printf("%d %d
    ",f[1][n],s[n]-f[1][n]);
    27     }
    28     return 0;
    29 }
    View Code

    E题:

    这真是水题(ーー゛)

    主要是找规律:

    如果有一段夹在1中间的0就要多翻两次,说明只要找有多少段夹在1中的0就行了,而还有特殊情况就是没被1夹住的0,

    没被夹住的0,也直接翻一次就行了。

     1 #include <stdio.h>
     2 #include <string.h>
     3 int main()
     4 {
     5     int sum=0;
     6     char a[50000];
     7     //freopen("E:/creat/in3_test.in","r",stdin);
     8     //freopen("E:/creat/in3_test.out","w",stdout);
     9     while(scanf("%s",a)!=EOF)
    10     {
    11         sum=0;
    12         int i=0,j;
    13         for(; i<strlen(a); i++)
    14         {
    15             if(a[i]=='0')
    16             {
    17                 if(a[i-1]=='1')sum++;//判断0前面是否是1
    18                 for(; i<strlen(a); i++) //判断是否有被1夹住
    19                     if(a[i]=='1') //判断0后面是否是1
    20                     {
    21                         i--;    //因为外循环回把i加1,这样会少判断一个,所以先减一
    22                         break;
    23                     }
    24                 sum++;//这个非常重要,不管是什么情况都包括了
    25             }
    26             else //如果是1的情况,就像往后找0
    27             {
    28                 for(; i<strlen(a); i++)
    29                     if(a[i]=='0')
    30                     {
    31                         i--;
    32                         break;
    33                     }
    34             }
    35         }
    36         printf("%d
    ",sum);
    37     }
    38     return 0;
    39 }
    复杂度过高的代码

    贴上学长的代码:

     1 #include<stdio.h>
     2 #include<string.h>
     3 char s[1000005];
     4 int main()
     5 {
     6     while(gets(s))
     7     {
     8         int k = 0;
     9         int i;
    10         for(i=1;s[i];i++)
    11         {
    12             if(s[i] != s[i-1]) {
    13                 k++;
    14             }
    15         }
    16         if(s[i-1] == '0') k++;
    17         printf("%d
    ",k);
    18     }
    19 
    20     return 0;
    学长的代码
  • 相关阅读:
    CSS媒体查询
    搜索关键词标注红色
    揭秘 | 小白如何0基础0元建站
    细说浏览器输入URL后发生了什么
    js问题总结
    vue elementui如何修改el-table头部样式
    h5开发微信公众号重定向到关注页面没有关注按钮 (微信你个坑)
    下拉展开动画
    html中常用的转义字符总结
    9个设计师常用的高清图库 不敢配图? 这9个免版权图库牢记心中!
  • 原文地址:https://www.cnblogs.com/tijie/p/6742851.html
Copyright © 2011-2022 走看看