zoukankan      html  css  js  c++  java
  • suoi62 网友跳 (暴搜+dp)

    传送门

    sbw太神啦orz

    首先N<=20可以直接暴搜

    然后玄学剪枝可以过18个点

    那么N<=40的时候,就把它拆成两半分别暴搜,再用dp拼起来

    对于前半段,设f[i][j]是开始高度为i,获得金币为j的方案数;对于后半段,设g[i][j]是结束高度为i,获得金币为j的方案数(离散化一下高度)

    然而V<=4e7,并不能直接记

    但其实每一段最多只有$2^{20}$种金币数,状压一下每一位选不选,再预处理出来这样的金币数是多少

    然后统计答案,$ans=sum{g[i][j]*f[k][l]},i>k,v[j]+v[l]>=M$

    给f做一个前缀和,给每个状态按v排序,可以$O(n*2^{n/2})$统计答案

    然后会MLE,注意到对于每种状态其实每个开始高度/结束高度 都只有选或者不选,做个前缀和最多也只有20

    把int改成unsigned char 就行了(逃

     1 #include<bits/stdc++.h>
     2 #define pa pair<int,int>
     3 #define CLR(a,x) memset(a,x,sizeof(a))
     4 using namespace std;
     5 typedef long long ll;
     6 const int maxn=45,maxs=(1<<20)+2;
     7 inline ll rd(){
     8     ll x=0;char c=getchar();int neg=1;
     9     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
    10     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    11     return x*neg;
    12 }
    13 int H[maxn],N,M,v1[maxs],v2[maxs],rk1[maxs],rk2[maxs];
    14 unsigned char f[42][maxs],g[42][maxs];
    15 void dfs1(int x,int tar,int h,int y){
    16     if(x>tar) return;
    17     dfs1(x+1,tar,h,y);
    18     if(H[x]>h) f[H[x]][y|(1<<(x-1))]++,dfs1(x+1,tar,H[x],y|(1<<(x-1)));
    19 }
    20 void dfs2(int x,int tar,int h,int y){
    21     if(x<tar) return;
    22     dfs2(x-1,tar,h,y);
    23     if(H[x]<h) g[H[x]][y|(1<<(x-tar))]++,dfs2(x-1,tar,H[x],y|(1<<(x-tar)));
    24 }
    25 
    26 inline bool cmp1(int a,int b){return v1[a]<v1[b];}
    27 inline bool cmp2(int a,int b){return v2[a]<v2[b];}
    28 int main(){
    29     // freopen("62.in","r",stdin);
    30     // freopen("62.out","w",stdout);
    31     int i,j,k;
    32     N=rd(),M=rd();
    33     for(i=1;i<=N;i++){
    34         rk1[i]=H[i]=rd(),rk2[i]=rd();
    35     }
    36     sort(rk1+1,rk1+N+1);
    37     int t=unique(rk1+1,rk1+N+1)-rk1-1;
    38     for(i=1;i<=N;i++)
    39         H[i]=lower_bound(rk1+1,rk1+t+1,H[i])-rk1;
    40     int m=N>>1;
    41     int n1=(1<<m)-1,n2=(1<<(N-m))-1;
    42     dfs1(1,m,0,0);
    43     dfs2(N,m+1,100,0);
    44     
    45     f[0][0]=1;g[t+1][0]=1;
    46     for(i=1;i<=t;i++){
    47         for(j=0;j<=n1;j++)
    48             f[i][j]+=f[i-1][j];
    49     }
    50     for(i=1;i<=n1;i++){
    51         for(j=1;j<=m;j++)
    52             if((i>>(j-1))&1) v1[i]+=rk2[j];
    53     }for(i=1;i<=n2;i++){
    54         for(j=1;j<=N-m;j++)
    55             if((i>>(j-1))&1) v2[i]+=rk2[j+m];
    56     }
    57     for(i=1;i<=n1;i++) rk1[i]=i;
    58     for(i=1;i<=n2;i++) rk2[i]=i;
    59     sort(rk1+1,rk1+n1+1,cmp1);
    60     sort(rk2+1,rk2+n2+1,cmp2);
    61     ll ans=0;
    62     for(i=1;i<=t+1;i++){
    63         ll s=0;
    64         for(j=0,k=n1;j<=n2;j++){
    65             for(;k>=0&&v1[rk1[k]]+v2[rk2[j]]>=M;k--)
    66                 s+=f[i-1][rk1[k]];
    67             ans+=s*g[i][rk2[j]];
    68         }
    69     }
    70     printf("%lld
    ",ans);
    71     return 0;
    72 }
  • 相关阅读:
    阿里云重磅发布DMS数据库实验室 免费体验数据库引擎
    阿里云移动端播放器高级功能---直播时移
    图解SQL的inner join、left join、right join、full outer join、union、union all的区别
    索引覆盖分析
    case when 性能优化
    Eclipse断点种类
    Eclipse高效率开发技巧
    VS Code编辑器
    正则表达式
    JDBC编程之预编译SQL与防注入式攻击以及PreparedStatement的使用教程
  • 原文地址:https://www.cnblogs.com/Ressed/p/9887324.html
Copyright © 2011-2022 走看看