[考试反思]1018csp-s模拟测试78(lrd day2) :规律

zkt没素质果然考炸了!

但是他考炸了和我一个分

这场的状态是真的不好,T3比较简单但没有做,一直干T2结果还是跪了

T1的哈希写挂了,模数比int大了结果一乘就炸long long了。

调了一个小时,傻逼哈希啊调了一个小时。。。心态初崩。

然后看到T2感觉不是特别难就写出来了。少考虑了一种情况挂成45分。

考后没多久就改过来了。

然后T2弄了一个小时40分钟左右,还剩40分钟看了一下T3的部分分感觉很不好打,不如写好T2,就完了。

注意时间分配。不要硬肝一道题。

扫描二维码关注公众号,回复: 7500174 查看本文章

不要怂大样例,对于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 }
View Code

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 }
注释版(2.2k)
 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 }
究级压码长版(969B,但其实单行不是很长所以并不算太压行)

样例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 }
View Code

猜你喜欢

转载自www.cnblogs.com/hzoi-DeepinC/p/11699730.html
今日推荐