• [考试反思]0408省选模拟65:直率


    计数专题测试???

    三题三计数,两个是$O(n^5)$。诡异。

    可能我的脑子比较适合想暴力,所以两个$O(n^5)$折腾来折腾去居然都弄出来了。

    然后$T2$一个$nlog$的题没时间写了,写暴力,结果还因为着急写挂了线段树丢了$30$分。

    $T2$其实也是个套路,花点时间想应该问题也不大。但是只能说这场考试明显的前松后紧了。

    本来时间没这么紧张的。但是还是效率不够高吧。。。

    T1:容器

    大意:序列,$k$次操作,第$i$次可以指定一个$L_i,R_i$使得区间$+1$。要求最后整个序列每个值都$le T$。求有多少中可行的操作方案。$n,k le 40$

    设$dp[i][j][[l]$表示考虑到序列第$i$位,有$j$次操作的左端点已确定,有$l$个操作的右端点未确定。转移带两个含义上的组合数就行。$O(n^5)$

    上下界并不满,可以卡一卡。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define mod 1011110011
     4 int C[44][44],dp[44][44][44],n,k,t;
     5 int mo(int x){return x>=mod?x-mod:x;}
     6 int main(){
     7     for(int i=0;i<41;++i)for(int j=C[i][0]=1;j<=i;++j)C[i][j]=mo(C[i-1][j-1]+C[i-1][j]);
     8     dp[0][0][0]=1; cin>>n>>k>>t;
     9     for(int i=1;i<=n+1;++i)for(int j=0;j<=k;++j)for(int l=0;l<=j&&l<=t;++l)if(dp[i-1][j][l])
    10         for(int x=0;x<=l;++x)for(int y=0;y<=k-j&&l-x+y<=t;++y)
    11             dp[i][j+y][l-x+y]=(dp[i][j+y][l-x+y]+1ll*dp[i-1][j][l]*C[l][x]%mod*C[k-j][y])%mod;
    12     cout<<dp[n+1][k][0]<<endl;
    13 }
    View Code

    T2:果树

    大意:点有颜色,求树上有多少路径满足路径上没有一种颜色出现了两次。每种颜色在树上最多出现$20$次。$n le 10^5$

    相当于有$20n$条限制:经过这两个点的路径不能同时选。

    如果这两个点是祖先后代关系,那么你就不能同时选择$x$的$y$方向外的子树的一个点以及$y$子树内的一个点。

    如果不是祖先后代关系那么限制就是不能同时选择$x,y$子树内的一点。

    放到$dfs$序就是一两个区间。如果放在二维的$dfs$序为下标的矩阵上那就是一个矩形。

    我们发现我们要求的就是这些矩形的并的补集的面积。经典的线段树扫描线。$O(20nlogn)$

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define S 800005
     4 int fir[S],l[S],to[S],col[S],dfr[S],tim,ec,n,dfn[S],w[S],val[S],f[20][S];long long ans;
     5 vector<int>v[S],_l[S],_r[S],_o[S];
     6 #define lc p<<1
     7 #define rc lc|1
     8 #define md (L+R>>1)
     9 void add(int l,int r,int v,int p=1,int L=1,int R=n){//cerr<<l<<' '<<r<<' '<<v<<endl;
    10     if(l<=L&&R<=r){w[p]+=v,val[p]=w[p]?R-L+1:val[lc]+val[rc];return;}
    11     if(l<=md)add(l,r,v,lc,L,md); if(r>md)add(l,r,v,rc,md+1,R);
    12     val[p]=w[p]?R-L+1:val[lc]+val[rc];
    13 }
    14 void link(int a,int b){l[++ec]=fir[a];fir[a]=ec;to[ec]=b;}
    15 void dfs(int p,int fa=0){
    16     dfn[p]=++tim; f[0][p]=fa;
    17     for(int i=1;i<17;++i)f[i][p]=f[i-1][f[i-1][p]];
    18     for(int i=fir[p];i;i=l[i])if(to[i]!=fa)dfs(to[i],p);
    19     dfr[p]=tim;
    20 }
    21 int getson(int y,int x){for(int i=16;~i;--i)if(dfn[f[i][y]]>dfn[x])y=f[i][y];return y;}
    22 void ins(int l,int r,int L,int R){
    23     if(l>r||L>R)return; //cerr<<l<<' '<<r<<' '<<L<<' '<<R<<endl;
    24     r++;
    25     _l[l].push_back(L); _r[l].push_back(R); _o[l].push_back(+1);
    26     _l[r].push_back(L); _r[r].push_back(R); _o[r].push_back(-1);
    27     r--; swap(l,L); swap(r,R); r++;
    28     _l[l].push_back(L); _r[l].push_back(R); _o[l].push_back(+1);
    29     _l[r].push_back(L); _r[r].push_back(R); _o[r].push_back(-1);
    30 }
    31 int main(){
    32     cin>>n; 
    33     for(int i=1;i<=n;++i)scanf("%d",&col[i]),v[col[i]].push_back(i);
    34     for(int i=1,a,b;i<n;++i)scanf("%d%d",&a,&b),link(a,b),link(b,a);
    35     dfs(1);
    36     for(int i=1;i<=n;++i)for(int j=0;j<v[i].size();++j)for(int k=j+1;k<v[i].size();++k){
    37         int x=v[i][j],y=v[i][k],z;
    38         if(dfn[x]>dfn[y])swap(x,y);
    39         if(dfn[y]<=dfr[x])z=getson(y,x),ins(1,dfn[z]-1,dfn[y],dfr[y]),ins(dfr[z]+1,n,dfn[y],dfr[y]);
    40         else ins(dfn[x],dfr[x],dfn[y],dfr[y]);
    41     }
    42     for(int i=1;i<=n;++i){
    43         for(int j=0;j<_l[i].size();++j)add(_l[i][j],_r[i][j],_o[i][j]);
    44         ans+=n-val[1];//cerr<<ans<<endl;
    45     }cout<<(ans-n)/2+n<<endl;
    46 }
    View Code

    T3:流浪

    大意:二维网格每次走一个格,求不能走到坏点,走了$t$步,其中经过次数$ge k$的格子个数的期望。$n,t le 30$

    由于期望的线性性,我们可以转而去对每一个格子求出它被经过$k$次的方案有多少种。

    下列所有路径均表示不经过坏点的路径,转移时判断即可。

    设$g[i][x][y]$表示走了$i$步,过程中不经过$(x,y)$最后停在了$(x,y)$的方案数。

    设$f[i][x][y]$表示从$(x,y)$出发走了$i$步中途不经过$(x,y)$最后停在了$(x,y)$的方案数。

    设$h[i][x][y]$表示从$(x,y)$出发走了$i$步中途不经过$(x,y)$最后停在了任意非$(x,y)$位置的方案数。

    转移都比较显然。最后枚举每一个格子去做一下背包就行了。

    每一部分的复杂度都是$O(n^5)$

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define mod 998244353
     4 int bad[66][66],n,k,t,ans,p[33][66][66],g[33][66][66],f[33][66][66],bp[33][33],h[33][66][66];
     5 void add(int&a,int b){a+=b;if(a>=mod)a-=mod;}
     6 int main(){
     7     cin>>t>>n>>k;
     8     for(int x,y,i=1;i<=n;++i)scanf("%d%d",&x,&y),bad[x+33][y+33]=1;
     9     for(int ex=-t;ex<=t;++ex)for(int ey=-t+abs(ex);ey<=t-abs(ex);++ey)if(!bad[33+ex][33+ey]){
    10         p[0][33][33]=1;ex+=33;ey+=33;
    11         for(int i=0;i<=t;++i)for(int x=-i;x<=i;++x)for(int y=-i+abs(x);y<=i-abs(x);++y)if(p[i][x+33][y+33]&&!bad[x+33][y+33]){
    12             x+=33;y+=33;
    13             if(x==ex&&y==ey)g[i][x][y]=p[i][x][y];
    14             else add(p[i+1][x+1][y],p[i][x][y]),add(p[i+1][x-1][y],p[i][x][y]),
    15                  add(p[i+1][x][y+1],p[i][x][y]),add(p[i+1][x][y-1],p[i][x][y]);
    16             p[i][x][y]=0; x-=33;y-=33;
    17         }ex-=33;ey-=33;
    18     }
    19     for(int ex=-t;ex<=t;++ex)for(int ey=-t+abs(ex);ey<=t-abs(ex);++ey)if(!bad[33+ex][33+ey]){
    20         p[0][33+ex][33+ey]=1;
    21         for(int i=0;abs(ex)+abs(ey)+i<=t;++i)for(int x=ex-i;x<=ex+i;++x)for(int y=ey-i+abs(x-ex);y<=ey+i-abs(x-ex);++y)if(p[i][x+33][y+33]&&!bad[x+33][y+33]){
    22             x+=33;y+=33;ex+=33;ey+=33;
    23             if(i&&x==ex&&y==ey)f[i][x][y]=p[i][x][y];
    24             else add(p[i+1][x+1][y],p[i][x][y]),add(p[i+1][x-1][y],p[i][x][y]),
    25                  add(p[i+1][x][y+1],p[i][x][y]),add(p[i+1][x][y-1],p[i][x][y]),add(h[i][ex][ey],p[i][x][y]);
    26             p[i][x][y]=0; x-=33;y-=33;ex-=33;ey-=33;
    27         }memset(p[t-abs(ex)-abs(ey)+1],0,sizeof p[0]);
    28     }
    29     for(int ex=-t;ex<=t;++ex)for(int ey=-t+abs(ex);ey<=t-abs(ex);++ey)if(!bad[33+ex][33+ey]){
    30         ex+=33;ey+=33;
    31         for(int i=0;i<=t;++i)bp[1][i]=g[i][ex][ey];
    32         for(int i=1;i<=t;++i)for(int j=0;j<=t;++j)if(bp[i][j])for(int l=j+1;l<=t;++l)
    33             bp[i+1][l]=(bp[i+1][l]+1ll*bp[i][j]*f[l-j][ex][ey])%mod;
    34         for(int i=k;i<=t;++i)for(int j=abs(ex-33)+abs(ey-33);j<=t;++j)ans=(ans+1ll*bp[i][j]*h[t-j][ex][ey])%mod;
    35         memset(bp,0,sizeof bp); ex-=33;ey-=33;
    36     }cout<<ans<<endl;
    37 }
    View Code
  • 相关阅读:
    AUPE学习第八章------进程控制
    软件工程中的一些图
    java_web用户的自动登录模块的实现
    opencv安装/usr/bin/ld: warning: libpcre.so.1, needed by //home/qian/anaconda3/lib/libglib-2.0.so.0, not found (try using -rpath or -rpath-link)问题
    ubuntu 安装使用多版本opencv
    基于运动学模型的模型预测控制
    粒子群滤波
    深度学习环境搭建
    安装uWebSocketIO
    最小二乘原理(3)——递归最小二乘
  • 原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/12661424.html
Copyright © 2020-2023  润新知