Noip模拟72 2021.10.9
T1 出了个大阴间题
真就以为他出了个大阴间题就没写,打个暴力就跑了
数据范围显然摆明是状压
设$f[sta][0/1]$表示在已经选择的集合$sta$中,$A$的最大值是$A$还是$A+1$
然后按照转移之后的集合内的最大值与当前集合的最大值的关系分情况转移,(这里的最大值不是$A$的最大值,是原数的最大值)
所以预处理一个集合内最大值的数组,转移可以达到$O(2^n n)$
1 #include<bits/stdc++.h> 2 #define int long long 3 using namespace std; 4 namespace AE86{ 5 inline int read(){ 6 int x=0,f=1;char ch=getchar(); 7 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 8 while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f; 9 }inline void write(int x,char opt='\n'){ 10 char ch[20];int len=0;if(x<0)x=~x+1,putchar('-'); 11 do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x); 12 for(register int i=len-1;i>=0;--i)putchar(ch[i]);putchar(opt);} 13 }using namespace AE86; 14 const int NN=19,mod=1e9+7; 15 int n,k,a[NN],smx[1<<NN]; 16 struct dp{int num,B,sum;}f[1<<19][2]; 17 namespace WSN{ 18 inline short main(){ 19 freopen("repair.in","r",stdin); freopen("repair.out","w",stdout); 20 n=read(); k=read(); int U=(1<<n)-1; 21 for(int i=1;i<=n;i++) a[i]=read(); 22 for(int i=1;i<=U;i++) for(int j=1;j<=n;j++) 23 if(i&(1<<j-1)) smx[i]=max(smx[i],a[j]); 24 for(int i=0;i<n;i++) f[1<<i][0].num=1; 25 for(int i=1;i<=U;i++) for(int j=1;j<=n;j++) if(!(i&(1<<j-1))){ 26 int to=i|(1<<j-1); 27 if(smx[to]==smx[i]&&smx[to]==a[j]){ 28 if(f[i][0].num){ 29 (f[to][1].num+=f[i][0].num)%=mod; 30 (f[to][1].B+=2*f[i][0].B%mod+f[i][0].num)%=mod; 31 (f[to][1].sum+=f[i][0].B+f[i][0].sum+f[i][0].num*k%mod*(smx[to]+1)%mod)%=mod; 32 } 33 if(f[i][1].num){ 34 (f[to][1].num+=f[i][1].num)%=mod; 35 (f[to][1].B+=2*f[i][1].B%mod+f[i][1].num)%=mod; 36 (f[to][1].sum+=f[i][1].B+f[i][1].sum+f[i][1].num*k%mod*(smx[to]+1)%mod)%=mod; 37 } 38 }else if(smx[to]==smx[i]+1||smx[to]==smx[i]){ 39 if(f[i][0].num){ 40 (f[to][0].num+=f[i][0].num)%=mod; 41 (f[to][0].B+=2*f[i][0].B%mod+f[i][0].num)%=mod; 42 (f[to][0].sum+=f[i][0].B+f[i][0].sum+f[i][0].num*k%mod*smx[to]%mod)%=mod; 43 } 44 if(f[i][1].num){ 45 (f[to][1].num+=f[i][1].num)%=mod; 46 (f[to][1].B+=2*f[i][1].B%mod+f[i][1].num)%=mod; 47 (f[to][1].sum+=f[i][1].B+f[i][1].sum+f[i][1].num*k%mod*(smx[to]+1)%mod)%=mod; 48 } 49 } 50 else{ 51 if(f[i][0].num){ 52 (f[to][0].num+=f[i][0].num)%=mod; 53 (f[to][0].B+=2*f[i][0].B%mod+f[i][0].num)%=mod; 54 (f[to][0].sum+=f[i][0].B+f[i][0].sum+f[i][0].num*k%mod*smx[to]%mod)%=mod; 55 } 56 if(f[i][1].num){ 57 (f[to][0].num+=f[i][1].num)%=mod; 58 (f[to][0].B+=2*f[i][1].B%mod+f[i][1].num)%=mod; 59 (f[to][0].sum+=f[i][1].B+f[i][1].sum+f[i][1].num*k%mod*smx[to]%mod)%=mod; 60 } 61 } 62 } 63 if(f[U][1].num) write(smx[U]+1,' '),write(f[U][1].sum); 64 else write(smx[U],' '),write(f[U][0].sum); 65 return 0; 66 } 67 } 68 signed main(){return WSN::main();}
T2 最简单辣快来做
说的挺简单,除了$T4$这个最难
看见绝对值就给他拆开绝对错不了,然后考虑四个方向统计贡献
比较妙的按照每一个点的$x,y$把原来的图分成$(n+1)^2$个小矩形,注意离散化
然后统计前缀和,这里的前缀和是指从一个格点到另一个格点需要的代价,是$a^i , b^j$的贡献,不是单纯的加和
处理完之后每次询问就可以$log(n)$的复杂度计算了,注意不想卡常的话使用光速幂,是一种类似分块的思想
可以做到$O(1)$出解的高幂次计算方法
1 #include<bits/stdc++.h> 2 using namespace std; 3 namespace AE86{ 4 inline int read(){ 5 int x=0,f=1;char ch=getchar(); 6 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 7 while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f; 8 }inline void write(int x,char opt='\n'){ 9 char ch[20];int len=0;if(x<0)x=~x+1,putchar('-'); 10 do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x); 11 for(register int i=len-1;i>=0;--i)putchar(ch[i]);putchar(opt);} 12 }using namespace AE86; 13 const int NN=2005; 14 int n,q,w,h,mod,a,b,dis1[NN],dis2[NN]; 15 struct sate{int h,x,y;}s[NN]; 16 int sum[NN][NN][5]; 17 inline int mo(int x){return x>=mod?x-mod:x;} 18 namespace gsm{ 19 const int KK=1e5+5; 20 int bl,A[KK],B[KK],pwa[KK],pwb[KK],k,r,res; 21 inline void init(){ 22 A[0]=B[0]=pwa[0]=pwb[0]=1; 23 bl=ceil(sqrt(1.0*max(w,h))); 24 for(int i=1;i<=bl;i++){ 25 A[i]=1ll*A[i-1]*a%mod; 26 B[i]=1ll*B[i-1]*b%mod; 27 } 28 for(int i=1;i<=bl;i++){ 29 pwa[i]=1ll*pwa[i-1]*A[bl]%mod; 30 pwb[i]=1ll*pwb[i-1]*B[bl]%mod; 31 } 32 } 33 inline int qmo(int x,int b){ 34 // cout<<x<<" "<<b<<endl; 35 if(b<0) return 0; k=b/bl; r=b%bl; 36 if(x==a) res=1ll*pwa[k]*A[r]%mod; 37 else res=1ll*pwb[k]*B[r]%mod; 38 return res; 39 } 40 }using namespace gsm; 41 inline void discrete(){ 42 sort(dis1+1,dis1+n+1); sort(dis2+1,dis2+n+1); 43 for(int i=1;i<=n;++i)s[i].x=lower_bound(dis1+1,dis1+n+1,s[i].x)-dis1; 44 for(int i=1;i<=n;++i)s[i].y=lower_bound(dis2+1,dis2+n+1,s[i].y)-dis2; 45 } 46 namespace WSN{ 47 inline short main(){ 48 // freopen("in.in","r",stdin); //freopen("bao.out","w",stdout); 49 freopen("satellite.in","r",stdin); freopen("satellite.out","w",stdout); 50 n=read();q=read();w=read();h=read();mod=read();a=read();b=read(); 51 for(int i=1;i<=n;++i) s[i].h=read(),dis1[i]=s[i].x=read(),dis2[i]=s[i].y=read(); 52 discrete(); init(); 53 for(int i=1;i<=n;++i) 54 sum[s[i].x][s[i].y][1]=sum[s[i].x][s[i].y][2]=sum[s[i].x][s[i].y][3]=sum[s[i].x][s[i].y][4]=s[i].h; 55 56 for(int i=1;i<=n;++i){ 57 for(int j=1;j<=n;++j) sum[i][j][1]=mo(sum[i][j][1]+1ll*sum[i][j-1][1]*qmo(b,dis2[j]-dis2[j-1])%mod); 58 for(int j=1;j<=n;++j) sum[i][j][1]=mo(sum[i][j][1]+1ll*sum[i-1][j][1]*qmo(a,dis1[i]-dis1[i-1])%mod); 59 for(int j=n;j;--j) sum[i][j][3]=mo(sum[i][j][3]+1ll*sum[i][j+1][3]*qmo(b,dis2[j+1]-dis2[j])%mod); 60 for(int j=n;j;--j) sum[i][j][3]=mo(sum[i][j][3]+1ll*sum[i-1][j][3]*qmo(a,dis1[i]-dis1[i-1])%mod); 61 } 62 for(int i=n;i;--i){ 63 for(int j=1;j<=n;++j) sum[i][j][2]=mo(sum[i][j][2]+1ll*sum[i][j-1][2]*qmo(b,dis2[j]-dis2[j-1])%mod); 64 for(int j=1;j<=n;++j) sum[i][j][2]=mo(sum[i][j][2]+1ll*sum[i+1][j][2]*qmo(a,dis1[i+1]-dis1[i])%mod); 65 for(int j=n;j;--j) sum[i][j][4]=mo(sum[i][j][4]+1ll*sum[i][j+1][4]*qmo(b,dis2[j+1]-dis2[j])%mod); 66 for(int j=n;j;--j) sum[i][j][4]=mo(sum[i][j][4]+1ll*sum[i+1][j][4]*qmo(a,dis1[i+1]-dis1[i])%mod); 67 } 68 int qx,qy,X,Y,x1,x2,y1,y2,tmp; 69 for(int o=1;o<=q;++o){ 70 qx=read(),qy=read(),X,Y; 71 X=lower_bound(dis1+1,dis1+n+1,qx)-dis1; 72 Y=lower_bound(dis2+1,dis2+n+1,qy)-dis2; 73 x1=X-1,x2=X,y1=Y-1,y2=Y,tmp=0; 74 tmp=mo(tmp+1ll*sum[x1][y1][1]*qmo(b,qy-dis2[y1])%mod*qmo(a,qx-dis1[x1])%mod); 75 if(x2<=n) tmp=mo(tmp+1ll*sum[x2][y1][2]*qmo(b,qy-dis2[y1])%mod*qmo(a,dis1[x2]-qx)%mod); 76 if(y2<=n) tmp=mo(tmp+1ll*sum[x1][y2][3]*qmo(b,dis2[y2]-qy)%mod*qmo(a,qx-dis1[x1])%mod); 77 if(y2<=n&&x2<=n) tmp=mo(tmp+1ll*sum[x2][y2][4]*qmo(b,dis2[y2]-qy)%mod*qmo(a,dis1[x2]-qx)%mod); 78 write(tmp); 79 } 80 return 0; 81 } 82 } 83 signed main(){return WSN::main();}
T3 是我的你不要抢
$hash$,$cao$过去就完了....
考试的时候字符串就用$hash$,别瞎搞什么$kmp$难想还难调
当时先想了个二分,非常假,我太傻。。。
后来就不知道哪里来的勇气码$kmp$,然后还是假,因为$bouder$的性质假的
其实直接拿$vector$存$hash$值然后生猛枚举匹配长度,再拿$map$存一下答案记忆化就可以水掉了
这么简单的思路,考场上沉迷看毛片无法自拔没想到,非常后悔,但是这道题的特殊性正好适应了这种无脑的暴力
造的最极限的数据不开$O2$卡到了九秒,开了$O2$就跑$1.4$,非常不懂
1 #include<bits/stdc++.h> 2 #define int long long 3 using namespace std; 4 namespace AE86{ 5 inline int read(){ 6 int x=0,f=1;char ch=getchar(); 7 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 8 while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f; 9 }inline void write(int x,char opt='\n'){ 10 char ch[20];int len=0;if(x<0)x=~x+1,putchar('-'); 11 do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x); 12 for(register int i=len-1;i>=0;--i)putchar(ch[i]);putchar(opt);} 13 }using namespace AE86; 14 typedef unsigned long long ULL; 15 const ULL base=131; 16 const int NN=6e5+5; 17 int n,q,len[NN]; 18 char ch[NN]; 19 ULL pw[NN]; 20 vector<ULL> ha[NN]; 21 map<pair<int,int>,int> mp; 22 inline void task(){ 23 scanf("%s",ch+1);int l=strlen(ch+1); 24 while(q--){int x=read(),y=read();write(l);} 25 } 26 inline ULL get(int i,int l,int r){ 27 return ha[i][r]-ha[i][l-1]*pw[r-l+1]; 28 } 29 namespace WSN{ 30 inline short main(){ 31 // freopen("in.in","r",stdin); freopen("bao.out","w",stdout); 32 freopen("string.in","r",stdin); freopen("string.out","w",stdout); 33 n=read();q=read(); if(n==1) return task(),0; 34 pw[0]=1; for(int i=1;i<NN;++i) pw[i]=pw[i-1]*base; 35 for(int i=1;i<=n;++i){ 36 scanf("%s",ch+1);len[i]=strlen(ch+1);ha[i].push_back(0); 37 for(int j=1;j<=len[i];++j){ 38 ULL last=ha[i].back(); 39 ha[i].push_back(last*base+(ULL)(ch[j]-'a'+1)); 40 } 41 } 42 for(int o=1;o<=q;++o){ 43 int x=read(),y=read(); 44 if(mp.find(make_pair(x,y))!=mp.end()){ 45 write(mp[make_pair(x,y)]);continue; 46 } 47 bool flag=0;int l=min(len[x],len[y]); 48 for(int i=l;i;--i) 49 if(get(x,len[x]-i+1,len[x])==get(y,1,i)){ 50 write(i);mp[make_pair(x,y)]=i;flag=1;break; 51 } 52 if(!flag) puts("0"),mp[make_pair(x,y)]=0; 53 } 54 return 0; 55 } 56 } 57 signed main(){return WSN::main();}
T4 显然也是我咕的