• [考试反思]0117省选模拟10:争夺


    T3出了一点锅,于是按IOI赛制打的。

    可能也是这辈子唯一一次好好打的IOI赛制了。

    提答,又沉里面了,进去就出不来。莫名的虚荣让我根本没有回头看传统题。

    于是的确在T3的80%时间里一直单题rk1,然而其实很慌,剩下两道题又怎样?

    运气好,T1特别水,T2数据水,T3用奇技淫巧多拿7分于是并列rk1了。

    数组没清空丢了1分。。。

    状态差的不行,一下午一道题都没改出来。。。咕到第二天也没改出来

    于是在第二天考试的时候写完三个暴力之后终于把T2A了。。。

    然后第二天考试就炸了,没什么好说的

    T1:食物链

    大意:就生物上那个。数条数。$n le 100000,mle 200000$

    当成生物题做就行。拓扑。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define S 200005
     4 int in[S],out[S],deg[S],l[S],fir[S],to[S],ec,n,m,q[S],t;long long dp[S],ans;
     5 void link(int a,int b){l[++ec]=fir[a];fir[a]=ec;to[ec]=b;in[b]++;out[a]++;}
     6 int main(){
     7     scanf("%d%d",&n,&m);
     8     for(int i=1,a,b;i<=m;++i)scanf("%d%d",&a,&b),link(a,b);
     9     for(int i=1;i<=n;++i)if(!in[i])q[++t]=i,dp[i]=1;else deg[i]=in[i];
    10     for(int h=1;h<=t;++h)for(int i=fir[q[h]];i;i=l[i]){
    11         dp[to[i]]+=dp[q[h]];deg[to[i]]--;
    12         if(!deg[to[i]])q[++t]=to[i];
    13     }
    14     for(int i=1;i<=n;++i)if(in[i]&&!out[i])ans+=dp[i];
    15     cout<<ans<<endl;
    16 }
    View Code

    T2:选点游戏

    大意:支持连边,询问某个联通块中最大独立集。点权为1。保证最后是个树。$nle 200000,mle 800000$

    维护子树信息的$LCT$。每个$splay$根维护的是一条实链,开四个变量维护这条链的顶端和底端分别选或不选的最优值。

    比$ddp$和正解都要好理解,好写一些。。。但是常数巨大。

    有一点小的分类讨论,其实代码非常好写。。。$1.6k$

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int S=200005,inf=20040124;
     4 int c[2][S],f[S],s[S],lz[S],dp0[S],dp1[S];
     5 #define lc c[0][p]
     6 #define rc c[1][p]
     7 int Max(int a,int b,int c){return max(max(a,b),c);}
     8 struct V{
     9     int __,_$,$_,$$;
    10     V(int a=0,int b=0,int c=0,int d=0){__=a,_$=b;$_=c;$$=d;}
    11     int val(){return Max(max(__,$_),_$,$$);}
    12     V operator+(V x){return V(Max(__+x.__,__+x.$_,_$+x.__),Max(__+x._$,__+x.$$,_$+x._$),Max($_+x.__,$_+x.$_,$$+x.__),Max($_+x._$,$$+x._$,$_+x.$$));}
    13 }v[S];
    14 bool nr(int p){return c[0][f[p]]==p||c[1][f[p]]==p;}
    15 void rev(int p){lz[p]^=1,swap(lc,rc),swap(v[p].$_,v[p]._$);}
    16 void up(int p){v[p]=V(dp0[p],-inf,-inf,dp1[p]+1);if(lc)v[p]=v[lc]+v[p];if(rc)v[p]=v[p]+v[rc];}
    17 void down(int p){if(lz[p])rev(lc),rev(rc),lz[p]=0;}
    18 void spin(int p){
    19     int F=f[p],G=f[F],D=c[1][F]==p,B=c[!D][p];
    20     if(nr(F))c[c[1][G]==F][G]=p; c[!D][p]=F; c[D][F]=B;
    21     if(B)f[B]=F; f[f[F]=p]=G; up(F);
    22 }
    23 void splay(int p){
    24     int tp=1,y=p,F;s[1]=p;
    25     while(nr(y))s[++tp]=y=f[y]; while(tp)down(s[tp--]);
    26     for(;F=f[p],nr(p);spin(p))if(nr(F))spin(c[1][F]==p^c[1][f[F]]==F?p:F); up(p);
    27 }
    28 void asas(int r){
    29     for(int y=0,p=r;p;p=f[y=p]){
    30         splay(p);
    31         dp0[p]+=v[rc].val()-v[y].val();
    32         dp1[p]+=max(v[rc].__,v[rc]._$)-max(v[y].__,v[y]._$);
    33         rc=y,up(p);
    34     }splay(r);
    35 }
    36 void make(int p){asas(p);rev(p);}
    37 void link(int x,int y){make(x);make(y);f[x]=y;dp0[y]+=v[x].val();dp1[y]+=max(v[x].__,v[x]._$);}
    38 int main(){//freopen("1.in","r",stdin);
    39     int n,m;cin>>n>>m;while(m-->0){
    40         int opt,x,y;scanf("%d",&opt);
    41         if(opt)scanf("%d%d",&x,&y),link(x,y);
    42         else scanf("%d",&x),make(x),printf("%d
    ",v[x].val());
    43     }
    44 }
    View Code

    T3:随机

    大意:看代码求输出的期望。

    $Test1:$随机返回$[1,n]$的随机数。

    $frac{1+n}{2}$

    1 #include<bits/stdc++.h>
    2 using namespace std;
    3 const int data[]={1,10,100,1024,10000,20000,50000,100000,524288,1000000};
    4 int main(){
    5     freopen("random1.out","w",stdout);
    6     for(int i=0;i<10;++i)printf("%.10Lf
    ",(1.0L+data[i])/2);
    7 }
    View Code

    $Test2:$$n$个$[1,1000000]$的随机变量的最小值。

    《地震后的幻想乡》的结论,$n$个随机$[0,1]$变量的最小值期望是$frac{1}{n+1}$

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int data[]={1,10,100,1024,10000,20000,50000,100000,524288,1000000};
     4 int main(){
     5     freopen("random2.out","w",stdout);
     6     for(int i=0;i<10;++i){
     7         __float128 ans=0;
     8         for(int x=1;x<=1000000;++x){
     9             ans+=pow(x/1000000.0L,data[i]);
    10         }printf("%.10Lf
    ",(long double)ans);
    11     }
    12 }
    View Code

    $Test3:$不断在$n$个变量中随机取值,求所有变量都被取过的期望步数。

    求取到下一个没取过的变量的期望步数进行累加。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int data[]={1,10,100,1024,10000,20000,50000,100000,524288,1000000};
     4 int sta[11111];
     5 int main(){
     6     freopen("random3.out","w",stdout);
     7     for(int i=0;i<10;++i){
     8         __float128 ans=0;
     9         for(int j=1;j<=data[i];++j)ans+=1.0L/j;
    10         printf("%.10Lf
    ",(long double)(ans*data[i]));
    11     }
    12 }
    View Code

    $Test4:$不断在$n$个变量中随机取值,求某一个变量被取过两次的期望步数。

    枚举步数,计算概率进行累加,概率很好算是个前缀积。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int data[]={1,10,100,1024,10000,20000,50000,100000,524288,1000000};
     4 int main(){
     5     freopen("random4.out","w",stdout);
     6     for(int i=0;i<=9;++i){
     7         __float128 pre=1,ans=0;
     8         for(int t=1;t<=data[i];++t){
     9             ans+=pre*t/data[i]*(t+1);
    10             pre*=((__float128)data[i]-t+0.0L)/data[i];
    11         }printf("%.10Lf
    ",(long double)ans);
    12     }
    13 }
    View Code

    $Test5:$求线段树区间询问时期望涉及多少个节点。

    考虑每个节点会在多少个方案中出现,当且仅当询问区间与当前节点区间相交且不包含父节点的完整区间。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int data[]={1,10,100,1024,10000,20000,50000,100000,524288,1000000};
     4 __float128 ans,all;int I;
     5 void build(int l,int r,int fl,int fr){
     6     int lp=l-1,rp=data[I]-r;
     7     ans+=all-(lp+1.0L)*lp/2-(rp+1.0L)*rp/2-1.0L*fl*(data[I]-fr+1);
     8     if(l==r)return;
     9     build(l,l+r>>1,l,r);build((l+r>>1)+1,r,l,r);
    10 }
    11 int main(){
    12     freopen("random5.out","w",stdout);
    13     for(int i=0;i<=9;++i){I=i;
    14         ans=0;all=(data[i]+1.0L)*data[i]/2;build(1,data[i],0,-1);
    15         printf("%.10Lf
    ",(long double)(ans/all));
    16     }
    17 }
    View Code

    $Test6:$求$Treap$期望深度和。

    考虑加入一个节点的贡献,设$dp[n]$为$n$个节点的树的答案,那么$dp[n]=frac{sumlimits_{i=1}^{n} dp[i-1]+dp[n-i]}{n}$。

    上边那个就是一个前缀和。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 long double dp[1000005],pre[1000005];
     4 const int data[]={1,10,100,1024,10000,20000,50000,100000,524288,1000000};
     5 int main(){
     6     freopen("random6.out","w",stdout);
     7     dp[1]=pre[1]=1;
     8     for(int i=2;i<=data[9];++i)dp[i]=2*pre[i-1]/i+i,pre[i]=pre[i-1]+dp[i];
     9     for(int i=0;i<=9;++i)printf("%.10Lf
    ",dp[data[i]]);
    10 }
    View Code

    $Test7:$不会。

    $Test8:$不断在$n$个变量中随机取值,不会取到已经取过的,取到时它的所有倍数也被取到。求所有变量都被取过的期望步数。

    每个节点被取到之可能是它的某个约数被取到,概率是均等的,所以答案是$sumlimits_{i=1}^{n} frac{1}{d(i)}$

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int data[]={1,10,100,1024,10000,20000,50000,100000,524288,1000000};
     4 __float128 ans;int I;
     5 int main(){
     6     freopen("random8.out","w",stdout);
     7     for(int i=0;i<=9;++i){
     8         ans=0;
     9         for(int x=1;x<=data[i];++x){
    10             int cnt=0;
    11             for(int y=1;y*y<=x;++y)if(x%y==0){
    12                 cnt++;if(y*y!=x)cnt++;
    13             }
    14             ans+=1.0L/cnt;
    15         }
    16         printf("%.10Lf
    ",(long double)ans);
    17     }
    18 }
    View Code

    $Test9:$值域为$10$,长度为$n$的随机序列的期望$LIS$。

    当$n$很大时答案直接近似成$10$。小点十进制压状态记搜$0.05s$都跑不到。

    $LIS$的转移只与前面每个值对应的最大$dp$值有关,压起来就搜就行了,实际上$1000$的点都跑不到$0.5s$

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int data[]={1,10,100,1024,10000,20000,50000,100000,524288,1000000};
     4 unordered_map<int,long double>M[101];
     5 int I,a[11],dp[11];long long ans,tms;
     6 int r[101][11],rr[101][11];
     7 long double sch100(int stp,int st){
     8     if(M[stp].find(st)!=M[stp].end())return M[stp][st];
     9     if(stp>6)cerr<<stp<<' '<<st<<endl;
    10     if(!stp)return st%10;int rst=st;
    11     for(int i=10;i;--i)r[stp][i]=st%10,st/=10;
    12     long double tot=0;
    13     for(int c=1;c<=10;++c){
    14         for(int i=1;i<=10;++i)rr[stp][i]=r[stp][i];
    15         rr[stp][c]=max(rr[stp][c],rr[stp][c-1]+1);
    16         if(c==10&&rr[stp][10]==10){tot+=1;break;}
    17         for(int s=c+1;s<=10;++s)rr[stp][s]=max(rr[stp][s],rr[stp][s-1]);
    18         register int nst=0;
    19         for(int i=1;i<=10;++i)nst=(nst<<3)+(nst<<1)+rr[stp][i];
    20         tot+=0.1*sch100(stp-1,nst);
    21     }return M[stp][rst]=tot;
    22 }
    23 int main(){
    24     freopen("random9.out","w",stdout);
    25     printf("%.10Lf
    ",sch100(100,0));
    26 }
    View Code

    $Test10:$不会。

  • 相关阅读:
    使用TransactionScope实现事务
    CYQ.Data 框架系列
    MVP
    DYCOM用于开发网络应用程序的通信部分功能的快速开发
    架构师要了解
    Entity Framework资源
    Sina Blogs
    关于TransactionScope出错:“与基础事务管理器的通信失败”的解决方法总结
    在西方的程序员眼里,东方的程序员是什么样的?
    net2.0事务学习
  • 原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/12208699.html
Copyright © 2020-2023  润新知