zoukankan      html  css  js  c++  java
  • 2019.3.7考试

    调T3沙茶错误调半天,最后T1没写暴力,0+100+90滚粗了

    T1 

    如果玩一玩/推一推可以发现两段前缀相同的序列p1和p2 构成的方案数是$Catalan(|p1|,|p2|)$,于是预处理从每对位置$a,b$开始的最长相同长度,然后就可以DP了:设$dp[i][j]$表示第一个序列从$i$第二个序列从$j$开始数的方案数

    转移1:两个位置不相同,直接$dp[i][j]+=dp[i+1][j]+dp[i][j+1]$

    转移2:两个位置相同,枚举两个序列向后延伸的长度转移,具体看代码

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int N=2005,M=4005,mod=998244353;
     6 int n,a[N],b[N],fac[M],inv[M],lst[N][N],dp[N][N];
     7 void Inc(int &x,int y)
     8 {
     9     x+=y;
    10     if(x>=mod) x-=mod;
    11 }
    12 template<class Type> void exGCD(Type a,Type b,Type &x,Type &y)
    13 {
    14     if(!b) {x=1,y=0; return;}
    15     else exGCD(b,a%b,y,x),y-=a/b*x;
    16 }
    17 template<class Type> Type Inv(Type x)
    18 {
    19     Type xx,yy;
    20     exGCD(x,mod,xx,yy);
    21     return (xx%mod+mod)%mod;
    22 }
    23 void Getfac(int Maxx)
    24 {
    25     fac[0]=inv[0]=1;
    26     for(int i=1;i<=Maxx;i++) fac[i]=1ll*fac[i-1]*i%mod;
    27     inv[Maxx]=Inv(fac[Maxx]);
    28     for(int i=Maxx-1;i;i--) inv[i]=1ll*inv[i+1]*(i+1)%mod;
    29 }
    30 int C(int a,int b)
    31 {
    32     return 1ll*fac[a]*inv[b]%mod*inv[a-b]%mod;
    33 }
    34 int Cat(int a,int b)
    35 {
    36     return (C(a+b,b)-C(a+b,b-1)+mod)%mod;
    37 }
    38 int DFS(int l1,int l2)
    39 {
    40     if(~dp[l1][l2]) return dp[l1][l2];
    41     if(l1>n||l2>n) return dp[l1][l2]=1;
    42     int ret=0;
    43     if(a[l1]!=b[l2]) 
    44         ret=(DFS(l1+1,l2)+DFS(l1,l2+1))%mod;
    45     else
    46     {
    47         int len=lst[l1][l2];
    48         ret=1ll*Cat(len,len)*DFS(l1+len,l2+len)%mod;
    49         for(int i=1;i<=len;i++)
    50         {
    51             int len1=l1+len+i-1,len2=l2+len+i-1;
    52             if(len1>n&&len2>n) break;
    53             if(len1<=n) Inc(ret,1ll*Cat(len+i,len-i)*DFS(l1+len+i,l2+len-i)%mod);
    54             if(len2<=n) Inc(ret,1ll*Cat(len+i,len-i)*DFS(l1+len-i,l2+len+i)%mod);
    55         }
    56     }
    57     return dp[l1][l2]=ret;
    58 }
    59 int main()
    60 {
    61     scanf("%d",&n);
    62     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    63     for(int i=1;i<=n;i++) scanf("%d",&b[i]);
    64     for(int i=n;i;i--)
    65         for(int j=n;j;j--)
    66             if(a[i]==b[j]) lst[i][j]=lst[i+1][j+1]+1;
    67     Getfac(2*n),memset(dp,-1,sizeof dp),printf("%d",DFS(1,1)); 
    68     return 0;
    69 }
    View Code

    T2

    这题考了***三遍了

    T3

    线段树上奇怪操作一定要考虑加上限制的暴力是不是就是对的

    考场上写的如果区间都一样统一修改,然后被卡了(随机0/1序列,每次整个区间加/减(x-1)再除以x)

    正解是如果 原最大值-新最大值=原最小值-新最小值 就修改,正确性是因为这时最大值和最小值相差不超过1,复杂度我放题解了

      1 #pragma GCC optimize(2)
      2 #include<cmath>
      3 #include<cstdio>
      4 #include<cctype>
      5 #include<cstring>
      6 #include<algorithm>
      7 #include<iostream>
      8 using namespace std;
      9 const int N=400005,inf=2e9;
     10 int a[N],mini[N],maxx[N],laz[N];
     11 int n,m,op,t1,t2,t3; long long sum[N];
     12 
     13 char BF[1<<23],*P1=BF,*P2=BF;
     14 char Gc(){return (P1==P2&&(P2=(P1=BF)+fread(BF,1,1<<21,stdin),P1==P2)?EOF:*P1++);}
     15 template<class Type> void Fread(Type &x)//fread
     16 {
     17     x=0; int lw=false; 
     18     char ch=Gc();
     19     while(!isdigit(ch))
     20         lw|=ch=='-',ch=Gc();
     21     while(isdigit(ch))
     22         x=(x<<1)+(x<<3)+(ch^48),ch=Gc();
     23     if(lw) x=-x;
     24 }
     25 char OBF[1<<23],*Ot=OBF;
     26 template<class Type> void W2(Type x) 
     27 {
     28     if(x>9) W2(x/10);
     29     *Ot++=x%10|48;
     30 }
     31 template<class Type> void Fwrite(Type x)//fwrite
     32 {
     33     if(x<0) *Ot++='-',x=-x;
     34     W2(x),*Ot++='
    ';
     35 }
     36 
     37 bool Ava(int x,int y)
     38 {
     39     return maxx[x]-floor((double)maxx[x]/y)==mini[x]-floor((double)mini[x]/y);
     40 }
     41 void Pushup(int nde)
     42 {
     43     int ls=nde*2,rs=nde*2+1;
     44     sum[nde]=sum[ls]+sum[rs];
     45     mini[nde]=min(mini[ls],mini[rs]);
     46     maxx[nde]=max(maxx[ls],maxx[rs]);
     47 }
     48 void Create(int nde,int l,int r)
     49 {
     50     if(l==r) 
     51         sum[nde]=mini[nde]=maxx[nde]=a[l];
     52     else
     53     {
     54         int mid=(l+r)>>1,ls=2*nde,rs=2*nde+1;
     55         Create(ls,l,mid),Create(rs,mid+1,r),Pushup(nde);
     56     }
     57 }
     58 void Release(int nde,int l,int r)
     59 {
     60     if(laz[nde])
     61     {
     62         int mid=(l+r)>>1,ls=2*nde,rs=2*nde+1,&lz=laz[nde];
     63         laz[ls]+=lz,laz[rs]+=lz;
     64         mini[ls]+=lz,mini[rs]+=lz;
     65         maxx[ls]+=lz,maxx[rs]+=lz;
     66         sum[ls]+=1ll*lz*(mid-l+1),sum[rs]+=1ll*lz*(r-mid),lz=0;
     67     }
     68 }
     69 void Add(int nde,int l,int r,int ll,int rr,int tsk)
     70 {
     71     if(l>rr||r<ll)
     72         return ;
     73     else if(l>=ll&&r<=rr)
     74         sum[nde]+=1ll*tsk*(r-l+1),mini[nde]+=tsk,maxx[nde]+=tsk,laz[nde]+=tsk;
     75     else
     76     {
     77         int mid=(l+r)>>1,ls=2*nde,rs=2*nde+1; Release(nde,l,r);
     78         Add(ls,l,mid,ll,rr,tsk),Add(rs,mid+1,r,ll,rr,tsk),Pushup(nde);
     79     }
     80 }
     81 void Change(int nde,int l,int r,int ll,int rr,int tsk)
     82 {
     83     if(l>rr||r<ll)
     84         return;
     85     else if(l>=ll&&r<=rr&&Ava(nde,tsk))
     86     {
     87         int task=floor((double)maxx[nde]/tsk)-maxx[nde]; 
     88         sum[nde]+=1ll*task*(r-l+1),mini[nde]+=task,maxx[nde]+=task,laz[nde]+=task;
     89     }
     90     else
     91     {
     92         int mid=(l+r)>>1,ls=2*nde,rs=2*nde+1;  Release(nde,l,r);
     93         Change(ls,l,mid,ll,rr,tsk);
     94         Change(rs,mid+1,r,ll,rr,tsk); Pushup(nde);
     95     }
     96 }
     97 long long Query_sum(int nde,int l,int r,int ll,int rr)
     98 {
     99     if(l>rr||r<ll)
    100         return 0;
    101     else if(l>=ll&&r<=rr)
    102         return sum[nde];
    103     else
    104     {
    105         int mid=(l+r)>>1,ls=2*nde,rs=2*nde+1; Release(nde,l,r);
    106         return Query_sum(ls,l,mid,ll,rr)+Query_sum(rs,mid+1,r,ll,rr);
    107     }
    108 }
    109 int Query_min(int nde,int l,int r,int ll,int rr)
    110 {
    111     if(l>rr||r<ll)
    112         return inf;
    113     else if(l>=ll&&r<=rr)
    114         return mini[nde];
    115     else
    116     {
    117         int mid=(l+r)>>1,ls=2*nde,rs=2*nde+1; Release(nde,l,r);
    118         return min(Query_min(ls,l,mid,ll,rr),Query_min(rs,mid+1,r,ll,rr));
    119     }
    120 }
    121 int main()
    122 {
    123     register int i;
    124     Fread(n),Fread(m);
    125     for(i=1;i<=n;i++) Fread(a[i]);
    126     Create(1,1,n);
    127     for(i=1;i<=m;i++)
    128     {
    129         Fread(op),Fread(t1),Fread(t2);
    130         if(op==1) Fread(t3),Add(1,1,n,t1,t2,t3);
    131         else if(op==2) Fread(t3),Change(1,1,n,t1,t2,t3);
    132         else if(op==3) Fwrite(Query_min(1,1,n,t1,t2));
    133         else Fwrite(Query_sum(1,1,n,t1,t2));
    134     }
    135     fwrite(OBF,Ot-OBF,1,stdout);
    136     return 0;
    137 }
    View Code
  • 相关阅读:
    深度学习方面的学术交流平台?
    如何用简单例子讲解 Q
    强化学习之Q-learning简介
    学完了在线课程?如何开启深度学习论文的阅读模式
    Java高级特性之枚举
    uboot启动流程
    Chromium网页Layer Tree创建过程分析
    Sql控制反转小尝试
    模拟日历计算 poj1008
    安卓零碎知识集中
  • 原文地址:https://www.cnblogs.com/ydnhaha/p/10490568.html
Copyright © 2011-2022 走看看