zoukankan      html  css  js  c++  java
  • [考试反思]1005csp-s模拟测试60:招魂

    最近总是好一场烂一场的。没有连续两场排名波动小于20的。。。

    没人管。反正大脸一点脸没有就又AK了。

    但是T3爆零这种事情吧。。。

    爆搜不是很难打,但是想优化想了半天剩的时间不够结果赶忙打出来了,然后就挂了。

    合理安排时间,要把码暴力的时间也考虑到,要检查。

    T1T2仍然挂上了对拍,所以没有全盘爆炸。

    总体来说是相对简单的一套题。

    T1:嘟嘟噜

    我的思路不太一样。但是复杂度是相似的。

    $O(m+log_{frac{m}{m-1}}frac{n}{m})$

    因为题面里说开无限栈了,然后我就想到了递归打法。

    int winner(int n)函数处理剩下n个人时最终胜者的目前编号。

    那么如果剩余人数n>m,那么你就可以把n/m个人同时干掉,从第n/m*m+1个人开始数来计算胜者

    如果n<=m的话,那就干掉一个人然后继续递归,和约瑟夫一样。

    这样的话每次递归,人数会在$-1$和$ imes frac{m-1}{m}$里选一个来 让它快速减小,可以得到上面的复杂度。

    据$o0O$打表证明,使n为1e9,当m取到大约1e6时函数的增长速度达到峰值,再之后的增长速度大约为线性。

    而本题数据范围1e5时的函数值仅仅是1e5多一点。

    总之O(可过)。

     1 #include<cstdio>
     2 int m,n,t;
     3 int winner(int n){
     4     if(n==1)return n;
     5     if(n<m)return (winner(n-1)+m-1)%n+1;
     6     int N=n/m,w=winner(n-N);
     7     if(N*m+w<=n)return N*m+w;
     8     w-=n-N*m;return (w-1)/(m-1)*m+(w-1)%(m-1)+1;
     9 }
    10 main(){
    11     scanf("%d",&t);
    12     while(t--)scanf("%d%d",&n,&m),printf("%d
    ",winner(n));
    13 }
    View Code

    T2:天才绅士少女助手克里斯蒂娜

    这道题是放假前让zkq出数据的那道题(这数据不是现成的嘛,还白给他送了个AC)

    化式子,拆平方,最后发现要求的就是$sumlimits_{i=l}^r sumlimits_{j=l}^r x_i^2 y_j^2 - x_i y_i x_j y_j$

    乘法分配律,得到的就是区间$(sumlimits_{i=l}^{r}x_i^2) imes(sumlimits_{i=l}^{r}y_i^2) - (sumlimits_{i=l}^{r}x_iy_i)^2$

    线段树或树状数组维护区间$x^2,y^2,xy$的和即可。注意常数。

     1 #include<cstdio>
     2 #define mod 20170927
     3 int cl[4000005],cr[4000005],x2[4000005],y2[4000005],xy[4000005],x[1000005],y[1000005],XY,X2,Y2;
     4 int read(){
     5     register int p=0;register char ch=getchar();
     6     while(ch<'0'||ch>'9')ch=getchar();
     7     while(ch>='0'&&ch<='9')p=(p<<3)+(p<<1)+ch-48,ch=getchar();
     8     return p;
     9 }
    10 #define lc p<<1
    11 #define rc p<<1|1
    12 int Mod(int p){return p>=mod?p-mod:p;}
    13 void up(int p){x2[p]=Mod(x2[lc]+x2[rc]);y2[p]=Mod(y2[lc]+y2[rc]);xy[p]=Mod(xy[lc]+xy[rc]);}
    14 void build(int p,int l,int r){
    15     cl[p]=l;cr[p]=r;
    16     if(l==r){long long x=read(),y=read();x2[p]=x*x%mod;y2[p]=y*y%mod;xy[p]=x*y%mod;return;}
    17     build(lc,l,l+r>>1);build(rc,(l+r>>1)+1,r);up(p);
    18 }
    19 void chg(int p,int pos){
    20     if(cl[p]==cr[p]){long long x=read(),y=read();x2[p]=x*x%mod;y2[p]=y*y%mod;xy[p]=x*y%mod;return;}
    21     chg(cr[lc]>=pos?lc:rc,pos);up(p);
    22 }
    23 void ask(int p,int l,int r){
    24     if(l<=cl[p]&&cr[p]<=r){XY=Mod(XY+xy[p]);X2=Mod(X2+x2[p]);Y2=Mod(Y2+y2[p]);return;}
    25     if(l<=cr[lc])ask(lc,l,r);if(r>=cl[rc])ask(rc,l,r);
    26 }
    27 main(){
    28     int n=read(),m=read(),opt,p;
    29     build(1,1,n);
    30     while(m--){opt=read();p=read();
    31         if(opt==1)chg(1,p);
    32         else XY=X2=Y2=0,ask(1,p,read()),printf("%d
    ",Mod((1ll*X2*Y2-1ll*XY*XY)%mod+mod));
    33     }
    34 }
    View Code

    T3:凤凰院凶真

    没想到。《算法竞赛进阶指南》上的原题竟然也不会做了。

    想的是三维,表示a串到了i位,b串到了j位,匹配的最大值是k的最大值。

    然而最后一维可以压掉,可以发现最后一维与前两维有关。

    我们只要强制b串的第j位必选就行了,这样就能得知最后一个选的是几,即最大值是几。

    简单的n3枚举。

     1 #include<cstdio>
     2 int n,m,x[5005],y[5005],fr[5001][5001],sta[5005],top;
     3 short dp[5001][5001];
     4 void upd(int i,int j,int li,int lj,int w){
     5     if(dp[i][j]>dp[li][lj]+1)return;
     6     dp[i][j]=dp[li][lj]+w;
     7     fr[i][j]=lj;
     8 }
     9 void get_back(int i,int j){if(i==0||j==0)return;
    10     int lj=fr[i][j];
    11     if(j!=lj)sta[++top]=y[j];
    12     get_back(i-1,lj);
    13 }
    14 int main(){
    15     scanf("%d",&n);
    16     for(int i=1;i<=n;++i)scanf("%d",&x[i]);
    17     scanf("%d",&m);
    18     for(int i=1;i<=m;++i)scanf("%d",&y[i]);
    19     for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)
    20         if(x[i]==y[j]){for(int k=0;k<j;++k)if(y[k]<x[i])upd(i,j,i-1,k,1);}
    21         else upd(i,j,i-1,j,0);
    22     int M=0;for(int i=1;i<=m;++i)if(dp[n][i]>dp[n][M])M=i;
    23     printf("%d
    ",dp[n][M]);
    24     get_back(n,M);
    25     for(int i=top;i;--i)printf("%d ",sta[i]);puts("");
    26 }
    View Code

    优化,边扫边记录上一层的最优决策。n2

     1 #include<cstdio>
     2 int n,m,x[5005],y[5005],fr[5001][5001],sta[5005],top;
     3 short dp[5001][5001];
     4 void upd(int i,int j,int li,int lj,int w){
     5     if(dp[i][j]>dp[li][lj]+1)return;
     6     dp[i][j]=dp[li][lj]+w;
     7     fr[i][j]=lj;
     8 }
     9 void get_back(int i,int j){if(i==0||j==0)return;
    10     int lj=fr[i][j];
    11     if(j!=lj)sta[++top]=y[j];
    12     get_back(i-1,lj);
    13 }
    14 int main(){
    15     scanf("%d",&n);
    16     for(int i=1;i<=n;++i)scanf("%d",&x[i]);
    17     scanf("%d",&m);
    18     for(int i=1;i<=m;++i)scanf("%d",&y[i]);
    19     for(int i=1;i<=n;++i){
    20         int bst=0,bp=0;
    21         for(int j=1;j<=m;++j){
    22             if(x[i]==y[j])upd(i,j,i-1,bp,1);
    23             else upd(i,j,i-1,j,0);
    24             if(y[j]<x[i]&&dp[i-1][j]>bst)bst=dp[i-1][j],bp=j;
    25         }
    26     }
    27     int M=0;for(int i=1;i<=m;++i)if(dp[n][i]>dp[n][M])M=i;
    28     printf("%d
    ",dp[n][M]);
    29     get_back(n,M);
    30     for(int i=top;i;--i)printf("%d ",sta[i]);puts("");
    31 }
    View Code

    回溯统计答案没什么好说的。

    思路积累:

    • 当dp维数过多导致复杂度高时,要考虑每维之间是否有联系,能否用一维表示另外一维。
  • 相关阅读:
    IDEA启动报错 NoClassDefFound
    IDEA手动导入jar包到maven本地库
    springboot FilterRegistrationBean 拦截器的使用
    springboot多模块controller访问的问题
    @Slf4j -- lombok.extern.slf4j.Slf4j;
    @mapper注解
    lombok
    Lodop打印小票
    spring security登录认证流程解析
    使用selenium实现简单网络爬虫抓取MM图片
  • 原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/11624603.html
Copyright © 2011-2022 走看看