• 10.18 模拟赛


    第一次160太不像话了

    第二题蛇皮错误并查集f[x]=find(f[x])写错了

    改完之后250 mmp

    T1:

    环形消灭虫子

    思路:

    首先可以想到枚举起点然后dp消灭虫子 复杂度n2

    然后我想到了一个蛇皮优化

    因为取到的点是不可能连在一起的

    所以我们的枚举有很多是重复的

    只需要枚举相邻的任意两个点就可以在它为起点的消灭虫子的答案中得到最优解

    因为我们的终点必定有一个是不会被取到的

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<cstdlib>
     7 #include<queue>
     8 #include<vector>
     9 #include<set>
    10 #include<stack>
    11 #define inf 2147483611
    12 #define ll long long
    13 #define MAXN 152550
    14 using namespace std;
    15 inline int read()
    16 {
    17     int x=0,f=1;
    18     char ch=getchar();
    19     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    20     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    21     return x*f;
    22 }
    23 int n,a[MAXN];
    24 ll dp[MAXN][2],ans;
    25 int main()
    26 {
    27     freopen("rob.in","r",stdin);
    28     freopen("rob.out","w",stdout);
    29     n=read();
    30     for(int i=0;i<n;i++) a[i]=read();
    31     for(int i=0;i<2;i++)
    32     {
    33         memset(dp,0,sizeof(dp));
    34         for(int j=0;j<n;j++)
    35         {
    36             dp[(i+j)%n][0]=max(dp[(j-1+i+n)%n][0],dp[(i+n+j-1)%n][1]);
    37             dp[(i+j)%n][1]=dp[(j-1+i+n)%n][0]+a[(i+j)%n];
    38         }
    39         ans=max(ans,dp[(i+n-1)%n][0]);
    40     }
    41     printf("%lld",ans);
    42 }
    View Code

     T2:

    有一个无向连通图

    删去一些边使得这些点恰好为两个连通块

    思路:

    我们可以找到一个最小生成树

    然后砍掉树里最大的边

    树里剩下的边权之和即为答案

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<cstdlib>
     7 #include<queue>
     8 #include<vector>
     9 #include<set>
    10 #include<stack>
    11 #define inf 2147483611
    12 #define ll long long
    13 #define MAXN 152550
    14 using namespace std;
    15 inline int read()
    16 {
    17     int x=0,f=1;
    18     char ch=getchar();
    19     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    20     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    21     return x*f;
    22 }
    23 struct data
    24 {
    25     int from,to,val;
    26     bool operator < (const data &a) const
    27     {
    28         return val<a.val;
    29     }
    30 }edge[MAXN];
    31 int n,m,cnt,f[MAXN];
    32 void add(int u,int v,int w) {edge[++cnt].from=u,edge[cnt].to=v,edge[cnt].val=w;}
    33 int find(int x) {return x==f[x]?x:f[x]=find(f[x]);}
    34 bool ok(int a,int b)
    35 {
    36     int fa=find(a),fb=find(b);
    37     if(fa==fb) return 1;
    38     else {f[fa]=fb;return 0;}
    39 }
    40 ll kruskal()
    41 {
    42     int tot=0;ll res=0;
    43     for(int i=1;i<=cnt;i++)
    44     {
    45         if(tot==n-2) break;
    46         if(!ok(edge[i].from,edge[i].to)) {tot++;res+=edge[i].val;}
    47     }
    48     return res;
    49 }
    50 int main()
    51 {
    52     freopen("destroy.in","r",stdin);
    53     freopen("destroy.out","w",stdout);
    54     n=read(),m=read();
    55     int a,b,c;
    56     for(int i=1;i<=n;i++) f[i]=i;
    57     while(m--)
    58     {
    59         a=read(),b=read(),c=read();
    60         add(a,b,c);
    61     }
    62     sort(edge+1,edge+cnt+1);
    63     printf("%lld",kruskal());
    64 }
    View Code

    T3:

    给一些数,求有多少种排列使他们满足A[i - 1] + A[i + 1] ≥ 2 × A[i] (2<=i<n)

    思路:

    (第一次不会直接上全排列暴力)  

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<cstdlib>
     7 #include<queue>
     8 #include<vector>
     9 #include<set>
    10 #include<stack>
    11 #define inf 2147483611
    12 #define ll long long
    13 #define MAXN 45
    14 #define MOD 998244353
    15 using namespace std;
    16 inline int read()
    17 {
    18     int x=0,f=1;
    19     char ch=getchar();
    20     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    21     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    22     return x*f;
    23 }
    24 int n,ans;
    25 struct data
    26 {
    27     int pos,val;
    28     bool operator < (const data &a) const
    29     {
    30         return val<a.val||(val==a.val&&pos<a.pos);
    31     }
    32 }a[MAXN];
    33 int main()
    34 {
    35     freopen("permutation.in","r",stdin);
    36     freopen("permutation.out","w",stdout);
    37     n=read();
    38     for(int i=1;i<=n;i++) a[i].val=read(),a[i].pos=i;
    39     sort(a+1,a+n+1);
    40     int i;
    41     while(1)
    42     {
    43         for(i=2;i<n;i++) if(a[i-1].val+a[i+1].val<2*a[i].val) break;
    44         if(i==n) ans++;
    45         ans%=MOD;
    46         if(!next_permutation(a+1,a+n+1)) break;
    47     }
    48     printf("%d",ans);
    49 }
    View Code

    正解:

    可以注意到n非常小

    我们可以简化一下条件a[i] - a[i - 1] ≤ a[i + 1] - a[i]

    然后对a数组排序

    这样的话,我们需要把最小值放在数列的中间,然后对于下一个数我们只能放在它的两边

    因此我们设一个dp四维数组 表示左边两个数为ai aj ak al 的符合题意的序列的个数

    但是最小值可能有很多个

    所以我们需要统计一下最小值的个数,然后对于答案*最小值的个数

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<cstdlib>
     7 #include<queue>
     8 #include<vector>
     9 #include<set>
    10 #include<stack>
    11 #define inf 2147483611
    12 #define ll long long
    13 #define MAXN 45
    14 #define MOD 998244353
    15 using namespace std;
    16 inline int read()
    17 {
    18     int x=0,f=1;
    19     char ch=getchar();
    20     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    21     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    22     return x*f;
    23 }
    24 int n,a[MAXN],cnt,tmp;
    25 ll dp[MAXN][MAXN][MAXN][MAXN],m,ans;
    26 int main()
    27 {
    28     freopen("permutation.in","r",stdin);
    29     freopen("permutation.out","w",stdout);
    30     n=read();
    31     for(int i=1;i<=n;i++) a[i]=read();
    32     sort(a+1,a+n+1);
    33     m=1;
    34     for(int i=1;i<=n;i++) if(a[i]==a[1]) {m=(m*i)%MOD;cnt++;}
    35     for(int i=2;i<=n-cnt+1;i++) a[i]=a[i+cnt-1];
    36     a[0]=a[1],dp[1][0][1][0]=1;
    37     n=n-cnt+1;
    38     for(int i=1;i<=n;i++)
    39         for(int j=0;j<n;j++)
    40             for(int k=1;k<=n;k++)
    41                 for(int l=0;l<n;l++)
    42                 {
    43                     if(!dp[i][j][k][l]) continue;
    44                     tmp=max(i,k)+1;
    45                     if(tmp==n+1) {(ans+=dp[i][j][k][l])%=MOD;continue;}
    46                     if(a[tmp]-a[i]>=a[i]-a[j]) (dp[tmp][i][k][l]+=dp[i][j][k][l])%=MOD;
    47                     if(a[tmp]-a[k]>=a[k]-a[l]) (dp[i][j][tmp][k]+=dp[i][j][k][l])%=MOD;
    48                 }
    49     (ans*=m)%=MOD;
    50     printf("%d",ans);
    51 }
    View Code
  • 相关阅读:
    Microsoft.NET User Group
    白话MVP 和 MVVM 【转】
    高效的二分法TOP MAX/TOP MIN分页存贮过程
    策略模式5
    说说我们项目组的例行会议
    合格的项目经理
    说说我们的招聘和面试
    web安全问题汇总
    ASP.NET中常用的优化性能方法
    说说我们安排的培训
  • 原文地址:https://www.cnblogs.com/yyc-jack-0920/p/7688457.html
Copyright © 2020-2023  润新知