zoukankan      html  css  js  c++  java
  • CSPS模拟86-87

    模拟86

    T1,烧水,按位统计贡献,利用某种sao操作避免数位dp

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 const int mod=1000000007;
     6 using namespace std;
     7 int n,m;
     8 int dp1[40],sum[40];
     9 int bin[40];
    10 inline void get1(int x)
    11 {
    12     memset(dp1,0,sizeof(dp1));
    13     if(x<0)return;
    14     for(int i=29;~i;--i)
    15     {
    16         dp1[i]=(x>>(i+1))+1;
    17         if(x&bin[i])dp1[i]=1ll*bin[i]*dp1[i]%mod;
    18         else{
    19             dp1[i]=1ll*(x>>(i+1))*bin[i]%mod;
    20             dp1[i]+=(x&(bin[i]-1));++dp1[i];
    21             if(dp1[i]>=mod)dp1[i]-=mod;
    22         }
    23     }
    24 }
    25 int main()
    26 {
    27     for(int i=0;i<=30;++i)bin[i]=1<<i;
    28     int T;scanf("%d",&T);
    29     while(T--)
    30     {
    31         scanf("%d%d",&m,&n);
    32         memset(sum,0,sizeof(sum));
    33         get1(n);
    34         for(int i=0;i<=30;++i)sum[i]+=dp1[i];
    35         get1(m-1);
    36         for(int i=0;i<=30;++i)sum[i]-=dp1[i];
    37         int ans=0;const int num=n-m+1;
    38         for(int i=0;i<=30;++i)
    39         {
    40             ans+=2ll*sum[i]%mod*(num-sum[i])%mod*bin[i]%mod;
    41             if(ans>=mod)ans-=mod;
    42         }
    43         ans=((ans%mod)+mod)%mod;
    44         cout<<ans<<endl;
    45         
    46     }
    47 }
    View Code

    T2,博弈,考场上推出了最小为0时的答案,以为能找出规律,连暴力都没打,kuku

    正解为用必败状态筛必胜状态来保证复杂度。%%%脸哥压表,处理出不合法状态hash掉,最后在数组里lower_bound即可。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define re register
     6 using namespace std;
     7 int n,m;
     8 int a[5];
     9 char dp[301][301][301];
    10 int main()
    11 {
    12     for(re short i=0;i<=300;++i)
    13     {
    14         for(re short j=0;j<=300;++j)
    15         {
    16             for(re short k=0;k<=300;++k)
    17             {
    18                 if(dp[i][j][k])continue;
    19                 for(re short o=1;o+i<=300;++o)dp[i+o][j][k]=1;
    20                 for(re short o=1;o+j<=300;++o)dp[i][j+o][k]=1;
    21                 for(re short o=1;o+k<=300;++o)dp[i][j][k+o]=1;
    22                 for(re short o=1;o+i<=300&&o+j<=300;++o)dp[i+o][j+o][k]=1;
    23                 for(re short o=1;o+i<=300&&o+k<=300;++o)dp[i+o][j][k+o]=1;
    24                 for(re short o=1;o+k<=300&&o+j<=300;++o)dp[i][j+o][k+o]=1;
    25                 for(re short o=1;o+i<=300&&o+k<=300&&o+j<=300;++o)dp[i+o][j+o][k+o]=1;
    26             }
    27         }
    28     }
    29     int T;scanf("%d",&T);
    30     while(T--)
    31     {
    32         scanf("%d%d%d",&a[1],&a[2],&a[3]);
    33         if(dp[a[1]][a[2]][a[3]])puts("Yes");
    34         else puts("No");
    35     }
    36 }
    View Code

    T3,dp,对前缀和取max优化。考场上想出了第三维表示四个状态(顶峰,底端,上升,下降),然而没想到转移。

    在最外层枚举区间数,对四种状态用4个变量分别维护最优点转移即可。%%%WWB_star,rnb,milk_feng让我认识到自己的错误

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define N 30040
     6 using namespace std;
     7 int n,K,ans;
     8 int a[N],sum[N],dp[205][N][5];
     9 const int inf=0x3f3f3f3f;
    10 int main()
    11 {
    12     memset(dp,-0x3f,sizeof(dp));
    13     scanf("%d%d",&n,&K);
    14     for(int i=1;i<=n;++i)
    15         scanf("%d",&a[i]),sum[i]=sum[i-1]+a[i];
    16     int mi=0,ma=0,mi2=0,ma2=0;
    17     for(int i=1;i<=n;++i){
    18         dp[1][i][2]=sum[i]-mi;
    19         dp[1][i][1]=ma-sum[i];
    20         dp[1][i][0]=dp[1][i][2];
    21         dp[1][i][3]=dp[1][i][1];
    22         mi=min(mi,sum[i]);ma=max(ma,sum[i]);
    23     }
    24     for(int j=2;j<K;++j){
    25         mi=ma=mi2=ma2=-inf;
    26         for(int i=j-1;i<=n;++i)
    27         {
    28             dp[j][i][2]=max(dp[j][i][2],ma+2*sum[i]);
    29             dp[j][i][1]=max(dp[j][i][1],mi-2*sum[i]);
    30             
    31             dp[j][i][0]=max(dp[j][i][0],mi2);
    32             dp[j][i][3]=max(dp[j][i][3],ma2);
    33             mi=max(mi,dp[j-1][i][2]+sum[i]*2);
    34             mi=max(mi,dp[j-1][i][0]+sum[i]*2);
    35             
    36             ma=max(ma,dp[j-1][i][1]-sum[i]*2);
    37             ma=max(ma,dp[j-1][i][3]-sum[i]*2);
    38             
    39             ma2=max(ma2,dp[j-1][i][1]);
    40             ma2=max(ma2,dp[j-1][i][3]);
    41             
    42             mi2=max(mi2,dp[j-1][i][2]);
    43             mi2=max(mi2,dp[j-1][i][0]);
    44         }
    45     }
    46     mi=ma=mi2=ma2=-inf;
    47     for(int i=K-1;i<=n;++i)
    48     {
    49         dp[K][i][2]=max(dp[K][i][2],ma+sum[i]);
    50         dp[K][i][1]=max(dp[K][i][1],mi-sum[i]);
    51         
    52         dp[K][i][0]=max(dp[K][i][0],mi2);
    53         dp[K][i][3]=max(dp[K][i][3],ma2);
    54         
    55         mi=max(mi,dp[K-1][i][2]+sum[i]);
    56         mi=max(mi,dp[K-1][i][0]+sum[i]);
    57         
    58         ma=max(ma,dp[K-1][i][1]-sum[i]);
    59         ma=max(ma,dp[K-1][i][3]-sum[i]);
    60         
    61         ma2=max(ma2,dp[K-1][i][1]);
    62         ma2=max(ma2,dp[K-1][i][3]);
    63         
    64         mi2=max(mi2,dp[K-1][i][2]);
    65         mi2=max(mi2,dp[K-1][i][0]);
    66         
    67         ans=max(ans,dp[K][i][2]);
    68         ans=max(ans,dp[K][i][1]);
    69     }
    70     printf("%d
    ",ans);
    71 }
    View Code
    300 145 120 50 110 220 122 160 130

    这个故事告诉我们:rp是个好东西(别败光了)

    模拟87,新的开始,勉强苟住位置(抢到Dybala的第八)

    T1,(妹子)maze

    考场上想了半天才想到是二分答案。然后就疯狂码码码,打了个代码测时长,发现极限数据甚至会达到十几秒,然后疯狂卡常

    最后当我手打堆打到一半,发现我的结构体重载运算符重载反了,赶紧改过来,发现还剩1分钟,慌的一比。。。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<bitset>
      6 #include<vector>
      7 #include<cmath>
      8 #include<queue>
      9 #define N 105
     10 using namespace std;
     11 const double eps=1e-5;
     12 const int dx[]={1,-1,0,0};
     13 const int dy[]={0,0,1,-1};
     14 int n,m,sx,sy,tx,ty;
     15 bool vst[N][N];
     16 double dis[N][N],s;
     17 int a[N][N];
     18 struct node{
     19     int x;
     20     int y;
     21     double z;
     22     friend bool operator <(const node &a,const node &b)
     23     {return a.z>b.z;}
     24 };
     25 /*
     26 struct QAQ{
     27     node a[100500];
     28     int tot;
     29     inline int size(){return tot;}
     30     inline void clear(){tot=0;}
     31     inline node top(){return a[1];}
     32     inline void pop()
     33     {
     34         a[1]=a[tot++];int i=1,j;
     35         while(1)
     36         {
     37             j=i<<1;
     38             if(j>tot)return;
     39             if(a[j+1]<a[j])
     40         }
     41     }
     42 
     43 }
     44 */
     45 priority_queue<node>q;
     46 inline void init()
     47 {
     48     for(register int i=1;i<=n;++i)
     49         for(register int j=1;j<=m;++j)
     50             dis[i][j]=1000000.0;
     51 }
     52 inline node mknd(int x,int y,double z)
     53 {
     54     node a;a.x=x,a.y=y,a.z=z;return a;
     55 }
     56 inline void dijk(double val)
     57 {
     58     while(q.size())q.pop();init();
     59     dis[sx][sy]=0.0;
     60     q.push(mknd(sx,sy,0.0));
     61     int xx,yy,x,y;double z;
     62     while(q.size())
     63     {
     64         x=q.top().x;y=q.top().y;z=q.top().z;q.pop();
     65         if(z!=dis[x][y])continue;if(x==tx&&y==ty)return;
     66         for(register int i=3;~i;--i)
     67         {
     68             xx=x+dx[i];yy=y+dy[i];
     69             if(a[xx][yy])continue;
     70             if(dx[i])
     71             {
     72                 if(dis[xx][yy]>z+val)
     73                 {
     74                     dis[xx][yy]=z+val;
     75                     q.push(mknd(xx,yy,dis[xx][yy]));
     76                 }
     77             }
     78             else
     79             {
     80                 if(dis[xx][yy]>z+1.0)
     81                 {
     82                     dis[xx][yy]=z+1.0;
     83                     q.push(mknd(xx,yy,dis[xx][yy]));
     84                 }
     85             }
     86         }
     87     }
     88 }
     89 inline void work()
     90 {
     91     double l=0.0,r=s,mid;
     92     while(r-l>3e-4){
     93         mid=(l+r)*0.5;dijk(mid);
     94         if(dis[tx][ty]-s>0.0)r=mid;
     95         else l=mid;
     96         if(fabs(dis[tx][ty]-s)<5e-4){l=mid;break;}
     97 //        printf("%.10lf %.10lf
    ",l,r);
     98     }
     99     printf("%.3lf
    ",l);
    100 }
    101 int main()
    102 {
    103 //    freopen("da.in","r",stdin);//freopen("my.out","w",stdout);
    104     scanf("%d%d%d%d%d%d",&n,&m,&sx,&sy,&tx,&ty);
    105     for(int i=1;i<=n;++i)
    106         for(int j=1,x;j<=m;++j)
    107             scanf("%d",&x),a[i][j]=x;
    108     
    109     a[sx][sy]=a[tx][ty]=0;
    110     dijk(1.0);if(dis[tx][ty]>100000.0)return 0;
    111     for(int i=1;i<=n;++i)a[i][0]=a[i][m+1]=1;
    112     for(int i=1;i<=m;++i)a[0][i]=a[n+1][i]=1;
    113     scanf("%lf",&s);work();return 0;
    114 }
    115 /*
    116 4 4
    117 1 1 4 4
    118 0 0 1 1
    119 1 0 0 0
    120 0 0 1 0
    121 0 0 0 0
    122 5
    123 */
    View Code

    T2,bird

    线段树稍显然,考虑去除重复贡献,用到了一些差分的思想,在左端点加入区间,右点存左点,dp值单点插入时暂且不加当前贡献,扫到右端点再加,保证不重复

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<bitset>
     6 #include<vector>
     7 #include<queue>
     8 #define N 500050
     9 using namespace std;
    10 int n,m;
    11 vector<int>v[N];
    12 int sum[N],dp[N];
    13 struct node{
    14     int l,r;
    15 }q[100050];
    16 int A,ans;
    17 int ma[N<<2],tag[N<<2];
    18 inline void upd(int g){ma[g]=max(ma[g<<1],ma[g<<1|1]);}
    19 inline void down(int g)
    20 {
    21     tag[g<<1]+=tag[g];
    22     ma[g<<1]+=tag[g];
    23     tag[g<<1|1]+=tag[g];
    24     ma[g<<1|1]+=tag[g];
    25     tag[g]=0;
    26 }
    27 inline void add(int g,int l,int r,int x,int y,int v)
    28 {
    29     if(l>y||r<x)return;
    30     if(l>=x&&r<=y){ma[g]+=v;tag[g]+=v;return;}
    31     if(tag[g])down(g);
    32     const int m=l+r>>1;
    33     add(g<<1,l,m,x,y,v);add(g<<1|1,m+1,r,x,y,v);
    34     upd(g);
    35 }
    36 inline int ask(int g,int l,int r,int x,int y)
    37 {
    38     if(l>y||r<x)return 0;
    39     if(l>=x&&r<=y)return ma[g];
    40     if(tag[g])down(g);
    41     const int m=l+r>>1;
    42     const int a1=ask(g<<1,l,m,x,y),a2=ask(g<<1|1,m+1,r,x,y);
    43     if(a1>a2)return a1;return a2;
    44 }
    45 int main()
    46 {
    47     scanf("%d%d",&n,&m);
    48     for(int i=1,l,r;i<=n;++i)
    49     {
    50         scanf("%d%d",&l,&r);
    51         if(r<0)continue;
    52         if(l<0)l=0;
    53         v[r+1].push_back(l);
    54         if(r>A)A=r;
    55         ++sum[l];
    56     }
    57     ++A;int al=0;
    58     for(int i=0;i<=A;++i)
    59     {
    60         al+=sum[i];
    61         for(int j=0;j<v[i].size();++j)
    62             add(1,0,A,v[i][j],i-1,1),--al;
    63         dp[i]=ask(1,0,A,0,i-m);
    64         ans=max(ans,dp[i]+al);
    65         add(1,0,A,i,i,dp[i]);
    66     }
    67     cout<<ans<<endl;
    68     return 0;
    69 }
    View Code

    T3,%%%脸哥

    话说脸哥是不是把推荐和反对放反了啊?

  • 相关阅读:
    light oj 1105 规律
    light oj 1071 dp(吃金币升级版)
    light oj 1084 线性dp
    light oj 1079 01背包
    light oj 1068 数位dp
    light oj 1219 树上贪心
    light oj 1057 状压dp TSP
    light oj 1037 状压dp
    矩阵快速幂3 k*n铺方格
    矩阵快速幂2 3*n铺方格
  • 原文地址:https://www.cnblogs.com/loadingkkk/p/11740988.html
Copyright © 2011-2022 走看看