[考试反思]1018csp-s模拟测试78(lrd day2) :规律
zkt没素质果然考炸了!
但是他考炸了和我一个分
这场的状态是真的不好,T3比较简单但没有做,一直干T2结果还是跪了
T1的哈希写挂了,模数比int大了结果一乘就炸long long了。
调了一个小时,傻逼哈希啊调了一个小时。。。心态初崩。
然后看到T2感觉不是特别难就写出来了。少考虑了一种情况挂成45分。
考后没多久就改过来了。
然后T2弄了一个小时40分钟左右,还剩40分钟看了一下T3的部分分感觉很不好打,不如写好T2,就完了。
注意时间分配。不要硬肝一道题。
不要怂大样例,对于DAG手动DFS一下其实可能很小。
哈希模数不要开到long long级别。
T1:串串香
暴力哈希。
1 #include<cstdio> 2 int max(int a,int b){return a>b?a:b;} 3 #define Hash_Mod 33514539 4 int n,m;char s[1000005];long long hsh[1000005],pw[1000005]; 5 int main(){//freopen("ex_ccx2.in","r",stdin); 6 pw[0]=1; 7 for(int i=1;i<=1000000;++i)pw[i]=pw[i-1]*29%Hash_Mod; 8 int t;scanf("%d",&t); 9 while(t--){ 10 scanf("%d%d%s",&n,&m,s+1);int max_match=0; 11 for(int i=1;i<=m;++i)hsh[i]=(hsh[i-1]*29+s[i]-'A')%Hash_Mod; 12 for(int i=1;i<m;++i)if(hsh[i]==((hsh[m]-hsh[m-i]*pw[i]%Hash_Mod)+Hash_Mod)%Hash_Mod) 13 if(n==1||hsh[m-i]==((hsh[m]-hsh[i]*pw[m-i]%Hash_Mod)+Hash_Mod)%Hash_Mod)max_match=i; 14 if(n==1&&max_match==0)puts("-1"); 15 else printf("%lld\n",(n-1ll)*m+max_match); 16 } 17 }
T2:糊涂图
代码注释写的很清楚。不懂的在评论区里问就好了。
1 //所谓新建了一条一次性边,其实就是在用到这条边时重新设定了先后手与起点位置,其余不变 2 //分类讨论是否经过了新建边即可 3 #include<cstdio> 4 #include<iostream> 5 using namespace std; 6 int n,m,s,fir[100005],l[300005],to[300005],cnt,out[100005],mx_win_p,mn_win_p; 7 int _fir[100005],_l[300005],_to[300005],_cnt; 8 double win[100005],reach[2][100005],lrd_ans1,lrd_ans2,ans1,ans2; 9 double tot_win,mx_win=-0.1,mn_win=1.1,mx2_win,mn2_win; 10 void link(int a,int b){l[++cnt]=fir[a];fir[a]=cnt;to[cnt]=b;out[b]++;} 11 void _link(int a,int b){_l[++_cnt]=_fir[a];_fir[a]=_cnt;_to[_cnt]=b;} 12 int main(){ 13 scanf("%d%d%d",&n,&m,&s);reach[0][s]=1; 14 for(int i=1,x,y;i<=m;++i)scanf("%d%d",&x,&y),link(y,x),_link(x,y); 15 scanf("%lf%lf",&lrd_ans1,&lrd_ans2); 16 //因为题目保证输入的边满足a<b,所以1~n就是一个合法的拓扑序 17 //求在这个点的先手胜率,需要逆向拓扑 18 for(int i=n;i;--i)for(int j=fir[i];j;j=l[j])win[to[j]]+=(1-win[i])/out[to[j]]; 19 //求从s开始用奇数/偶数步到达每一个点的概率,正向拓扑 20 for(int i=1;i<=n;++i)for(int j=_fir[i];j;j=_l[j]) 21 reach[1][_to[j]]+=reach[0][i]/out[i],reach[0][_to[j]]+=reach[1][i]/out[i]; 22 for(int i=1;i<=n;++i){ 23 tot_win+=win[i]; 24 if(mx_win<=win[i])mx2_win=mx_win,mx_win_p=i,mx_win=win[i]; 25 if(mn_win>=win[i])mn2_win=mn_win,mn_win_p=i,mn_win=win[i]; 26 } 27 //最大胜率,就是建边把自己引向胜率最大的点或把对方引向胜率最小的点 28 for(int i=1;i<=n;++i){//枚举起点 29 double mx=i==mx_win_p?mx2_win:mx_win,mn=i==mn_win_p?mn2_win:mn_win;//不能是自环,所以如果撞了就要取次大值 30 ans1=max(ans1,max( 31 (win[s]-reach[0][i]*win[i]-reach[1][i]*(1-win[i]))//根本没路过起点的胜率 32 +reach[0][i]/(out[i]+1)*(1-mx)//lrd走了新边 33 +reach[1][i]/(out[i]+1)*mx//对手走了新边 34 +reach[0][i]*out[i]/(out[i]+1)*win[i]//路过起点然后轮到达哥继续走 35 +reach[1][i]*out[i]/(out[i]+1)*(1-win[i])//u路过起点轮到对手继续走 36 , 37 (win[s]-reach[0][i]*win[i]-reach[1][i]*(1-win[i]))//根本没路过起点的胜率 38 +reach[0][i]/(out[i]+1)*(1-mn)//lrd走了新边 39 +reach[1][i]/(out[i]+1)*mn//对手走了新边 40 +reach[0][i]*out[i]/(out[i]+1)*win[i]//路过起点然后轮到达哥继续走 41 +reach[1][i]*out[i]/(out[i]+1)*(1-win[i])//u路过起点轮到对手继续走 42 )); 43 } 44 //平均胜率,就是建到其它任意点的平均胜率,还是分先后手 45 for(int i=1;i<=n;++i){ 46 double tot=(tot_win-win[i])/(n-1); 47 ans2+=(1-(reach[0][i]+reach[1][i])/(out[i]+1))*win[s]//没用新边 48 +reach[0][i]/(out[i]+1)*(1-tot)//lrd走了新边 49 +reach[1][i]/(out[i]+1)*tot;//对手走了新边 50 } 51 printf("%.3lf %.3lf\n",lrd_ans1>-0.5?lrd_ans1:ans1,lrd_ans2>-0.5?lrd_ans2:ans2/n); 52 }
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 int n,m,s,fir[100005],l[300005],to[300005],c,O[100005],_fir[100005],_l[300005],_to[300005],_c; 5 double w[100005],r[100005],R[100005],A1,A2,Tot,Mx,Mn=1,p,tot; 6 void L(int a,int b){l[++c]=fir[a];fir[a]=c;to[c]=b;O[b]++;} 7 void _L(int a,int b){_l[++_c]=_fir[a];_fir[a]=_c;_to[_c]=b;} 8 int main(){ 9 scanf("%d%d%d",&n,&m,&s);r[s]=1; 10 for(int i=1,x,y;i<=m;++i)scanf("%d%d",&x,&y),L(y,x),_L(x,y); 11 for(int i=n;i;--i)for(int j=fir[i];j;j=l[j])w[to[j]]+=(1-w[i])/O[to[j]]; 12 for(int i=1;Tot+=w[i],Mx=max(Mx,w[i]),Mn=min(Mn,w[i]),i<=n;++i)for(int j=_fir[i];j;j=_l[j])R[_to[j]]+=r[i]/O[i],r[_to[j]]+=R[i]/O[i]; 13 for(int i=1;p=r[i]<R[i]?Mx:Mn,i<=n;++i)A1=max(A1,((w[s]-r[i]*w[i]-R[i]*(1-w[i]))+r[i]/(O[i]+1)*((1-p)+O[i]*w[i])+R[i]/(O[i]+1)*(p+O[i]*(1-w[i])))); 14 for(int i=1;tot=(Tot-w[i])/(n-1),i<=n;++i)A2+=(1-(r[i]+R[i])/(O[i]+1))*w[s]+r[i]/(O[i]+1)*(1-tot)+R[i]/(O[i]+1)*tot; 15 printf("%.3lf %.3lf\n",A1,A2/n); 16 }
样例3简化图:
T3:木叶下
维护子树内的贡献,父亲方向上的贡献,对于每个点p其父亲f除却p以外的儿子的贡献。
树上倍增,还需要维护子树最大,第二大,第三大。
1 #include<cstdio> 2 int max(int a,int b){return a>b?a:b;} 3 int fi[200005],se[200005],th[200005],fir[200005],l[400005],to[400005],son[200005],ANS; 4 int n,m,cnt,fip[200005],sep[200005],fav[200005][20],f[200005][20],dep[200005],F[200005]; 5 void link(int a,int b){l[++cnt]=fir[a];fir[a]=cnt;to[cnt]=b;} 6 void dfs(int p,int fa){ 7 f[p][0]=fa;dep[p]=dep[fa]+1; 8 for(int i=1;i<=18;++i)f[p][i]=f[f[p][i-1]][i-1]; 9 for(int i=fir[p];i;i=l[i])if(to[i]!=fa){ 10 dfs(to[i],p);int mx=son[to[i]]+1; 11 if(mx>fi[p])th[p]=se[p],se[p]=fi[p],sep[p]=fip[p],fi[p]=mx,fip[p]=to[i]; 12 else if(mx>se[p])th[p]=se[p],se[p]=mx,sep[p]=to[i]; 13 else if(mx>th[p])th[p]=mx; 14 if(son[p]<mx)son[p]=mx; 15 } 16 for(int i=fir[p];i;i=l[i])if(to[i]!=fa){ 17 if(fip[p]!=to[i])fav[to[i]][0]=fi[p]; 18 else if(sep[p]!=to[i])fav[to[i]][0]=se[p]; 19 else fav[to[i]][0]=th[p]; 20 }ANS=max(ANS,fi[p]+se[p]); 21 } 22 void DFS(int p,int fa){ 23 for(int i=1;i<=18;++i)fav[p][i]=max(fav[p][i-1],fav[f[p][i-1]][i-1]); 24 for(int i=fir[p];i;i=l[i])if(to[i]!=fa){ 25 F[to[i]]=F[p]; 26 if(fip[p]==to[i])F[to[i]]=max(F[to[i]],se[p]); 27 else F[to[i]]=max(F[to[i]],fi[p]); 28 F[to[i]]++; 29 DFS(to[i],p); 30 } 31 32 } 33 int main(){//freopen("ex_myx2.in","r",stdin);freopen("my.out","w",stdout); 34 //freopen("r.out","r",stdin);freopen("t3.out","w",stdout); 35 scanf("%d",&n); 36 for(int i=1,x,y;i<n;++i)scanf("%d%d",&x,&y),link(x,y),link(y,x); 37 dfs(1,0);DFS(1,0); 38 scanf("%d",&m);int a,b,ans,sub,lca,ra,rb; 39 while(m--){ 40 scanf("%d%d",&a,&b);ans=0;//printf("%d %d\n",a,b); 41 if(a==b){printf("%d\n",(ANS>>1)+1);continue;} 42 sub=dep[a]-dep[b];if(sub<0)a^=b^=a^=b,sub=-sub;ra=a;rb=b; 43 for(int i=18;~i;--i)if(sub&1<<i)a=f[a][i]; 44 if(a==b)lca=a,ans=son[ra]; 45 else{ 46 for(int i=18;~i;--i)if(f[a][i]!=f[b][i])a=f[a][i],b=f[b][i]; 47 lca=f[a][0];ans=max(son[ra],son[rb]); 48 }a=ra;b=rb; 49 sub=dep[a]-dep[lca]-1; 50 for(int i=18;~i;--i)if(sub&1<<i)ans=max(ans,fav[a][i]),a=f[a][i]; 51 sub=dep[b]-dep[lca]-1; 52 if(sub>0)for(int i=18;~i;--i)if(sub&1<<i)ans=max(ans,fav[b][i]),b=f[b][i]; 53 if(!(fip[lca]==a||fip[lca]==b))ans=max(ans,fi[lca]); 54 else if(!(sep[lca]==a||sep[lca]==b))ans=max(ans,se[lca]); 55 else ans=max(ans,th[lca]); 56 ans=max(ans,F[lca]); 57 printf("%d\n",ans); 58 }//printf("%d\n",fav[6][0]); 59 }
$Fate \ is \ Fake$