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
原文地址:https://www.cnblogs.com/ydnhaha/p/10490568.html