zoukankan      html  css  js  c++  java
  • [考试反思]1012csp-s模拟测试70:盘旋

    这套题比较烂。。。

    上来看到T2是原题,一想上一次考试遇到原题就不换,这次应该也是,于是直接开始码,码了一半然后换题了

    T1打表找规律或者推式子都不难。。。

    T2水的一匹暴力剪枝即可,但是我并不知道数据那么那么水所以还花了很多时间优化

    T3神奇的大模拟,挺有意思但是考场上不可能有人能拿到20+

    所以因为题比较烂,所以我就上去了?

    隔了一场之后RP守恒又恢复了?

    啊啊不要乱说啊再过十几分钟就又要考一场了啊。。。

    T1:木板

    具体化式子也就是个初中数学,结论就是(最大平方因子的平方根-1)<<3,打个100的表就出来了

    1 #include<cstdio>
    2 int main(){
    3     long long n,mx;scanf("%lld",&n);
    4     while(n){
    5         for(long long i=1;i*i<=n;++i)if(n%(i*i)==0)mx=i;
    6         printf("%lld
    ",(mx-1)<<3);scanf("%lld",&n);
    7     }
    8 }
    183B

    T2:打扫卫生

    看到数据范围,直接上根号。

    dp[i]表示以i为某一段的结尾,到i为止的最优dp值。

    几个比较明显的性质:

    0)$dp[i]<=i$

    1)颜色数超过$sqrt{i}$时不必再考虑从前面转移。否则转移来的值不满足上一条

    2)任意$i<j$有$dp[i]<=dp[j]$

    运用第二条打一个暴力,及时跳出。

     1 #include<cstdio>
     2 #include<iostream>
     3 using namespace std;
     4 int dp[40005],n,m,a[40005],al[40005],cal;
     5 int min(int a,int b){return a<b?a:b;}
     6 int main(){//freopen("2.in","r",stdin);freopen("bl.out","w",stdout);
     7     scanf("%d%d",&n,&m);
     8     for(int i=1;i<=n;++i){scanf("%d",&a[i]);if(a[i]==a[i-1])i--,n--;}
     9     for(int i=1;i<=n;++i)dp[i]=i;
    10     for(int i=2;i<=n;++i){
    11         int knd=0;
    12         for(int j=i-1;~j;--j){cal++;
    13             knd+=al[a[j+1]]==i?0:1;
    14             if(knd*knd>=dp[i])break;
    15             al[a[j+1]]=i;
    16             dp[i]=min(dp[i],dp[j]+knd*knd);
    17         }
    18     }printf("%d
    ",dp[n]);std:cerr<<cal<<endl;
    19 }
    800ms

    然后你就AC了。

    显然复杂度还是$O(n^2)$的。对拍随机数据,其最内层循环进入了900000000次。

    可见题目的数据还不如随机数据。

    优化,上述做法的复杂度瓶颈在于你只保证了你扫了$sqrt{i}$个颜色,但不一定是$sqrt{i}$个位置。

    那么其实可以发现,从i往前扫,到连续的一段区间上的颜色数都相等,根据那第2条性质,那么你直接从这个区间的左端点转移即可。

    那么现在的问题是:你要O(1)找到从位置i往前最远到哪里有恰好k种颜色。

    考虑位置i,它的颜色为p,那么你找到上一次p出现的位置,这个位置以后再也不会贡献颜色数了,以后不会从它转移。

    那么很自然的想法就是一个链表,把上一个p跳过,这一个p加入。

    这样沿着链表往前跳,每次必然遇到一个新颜色,颜色数+1。

    根据性质1,你最多跳$sqrt{i}$种颜色。

    总复杂度$nsqrt{n}$。

     1 #include<cstdio>
     2 int dp[40005],n,m,a[40005],lp[40005],lst[40005],nxt[40005];
     3 int min(int a,int b){return a<b?a:b;}
     4 int main(){
     5     scanf("%d%d",&n,&m);
     6     for(int i=1;i<=n;++i){scanf("%d",&a[i]);if(a[i]==a[i-1])i--,n--;}
     7     for(int i=1;i<=n;++i)dp[i]=i;
     8     lst[40001]=0;nxt[0]=40001;
     9     for(int i=1;i<=n;++i){
    10         int knd=0,l=lp[a[i]];
    11         lp[a[i]]=i;
    12         if(l)lst[nxt[l]]=lst[l],nxt[lst[l]]=nxt[l];
    13         nxt[lst[40001]]=i,lst[i]=lst[40001],lst[40001]=i,nxt[i]=40001;
    14         for(int j=lst[40001];j;j=lst[j]){
    15             knd++;
    16             if(knd*knd>=dp[i])break;
    17             dp[i]=min(dp[i],dp[lst[j]]+knd*knd);
    18         }
    19     }printf("%d
    ",dp[n]);
    20 }
    View Code

    T3:骆驼

    大模拟。

    结论是5*5的网格任意选取起点终点都有解。

    所以把这些5*5网格拼接一下就好了。

    分奇偶讨论,有些人需要特判5和15的点。

    最好好好利用关键位置(3,3),能简单不少(但是我用的不是。。所以特别麻烦)

    大网格的拼接也可以搜索,不一定要执迷于for循环自行讨论。。。

    终于打出来了!

     1 #include<cstdio>
     2 int n,s[6][6][6][6][6][6],ans[1001][1001],sx,sy,ex,ey,ord[201][201];
     3 const int xx[]={0,0,3,-3,2,2,-2,-2};
     4 const int yy[]={3,-3,0,0,2,-2,2,-2};
     5 #define tx x+xx[i]
     6 #define ty y+yy[i]
     7 bool sch(int stp,int x,int y){
     8     if(stp==25)return x==ex&&y==ey;
     9     if(x==ex&&y==ey)return false;
    10     for(int i=0;i<=7;++i)if(tx>0&&ty>0&&tx<=5&&ty<=5&&!s[sx][sy][ex][ey][tx][ty]){
    11         s[sx][sy][ex][ey][tx][ty]=stp+1;
    12         if(sch(stp+1,tx,ty))return true;
    13         s[sx][sy][ex][ey][tx][ty]=0;
    14     }return false;
    15 }
    16 void fill(int x,int y,int sx,int sy,int ex,int ey){
    17     for(int i=1;i<=5;++i)for(int j=1;j<=5;++j)ans[x*5-5+i][y*5-5+j]=s[sx][sy][ex][ey][i][j]+6+25*ord[x][y];
    18 }
    19 int main(){scanf("%d",&n);
    20     for(int i=1;i<=5;++i)for(int j=1;j<=5;++j)for(int k=1;k<=5;++k)for(int l=1;l<=5;++l)
    21         s[sx=i][sy=j][ex=k][ey=l][i][j]=1,sch(1,i,j);
    22     int bl=n/5;
    23     if(bl==1)for(int i=1;i<=5;++i)for(int j=1;j<=5;++j)ans[i][j]=s[1][1][3][3][i][j];
    24     else if(bl==3){
    25         for(int i=1;i<=5;++i)for(int j=1;j<=5;++j)ans[i][j]=s[1][1][3][3][i][j]>6?n*n-25+s[1][1][3][3][i][j]:s[1][1][3][3][i][j];//(1,1)
    26         ord[3][1]=1;ord[3][2]=2;ord[3][3]=3;
    27         ord[2][3]=4;ord[1][3]=5;ord[2][2]=6;ord[1][2]=7;
    28         fill(2,1,2,1,5,3);fill(3,1,2,1,5,3);fill(3,2,5,1,3,5);fill(3,3,3,3,1,3);fill(2,3,3,3,1,3);
    29         fill(1,3,3,3,5,1);fill(2,2,2,4,1,3);fill(1,2,3,3,1,2);
    30     }
    31     else if(bl&1){int alc=-2;
    32         for(int i=1;i<=bl;++i)ord[i][1]=++alc;
    33         for(int i=bl;i>2;--i)if(i&1)for(int j=2;j<=bl;++j)ord[i][j]=++alc;
    34             else for(int j=bl;j>1;--j)ord[i][j]=++alc;
    35         ord[2][bl]=++alc;ord[1][bl]=++alc;
    36         for(int i=bl-1;i>1;--i)if(i&1)ord[1][i]=++alc,ord[2][i]=++alc;
    37             else ord[2][i]=++alc,ord[1][i]=++alc;
    38         for(int i=2;i<bl;++i)fill(i,1,2,1,5,3);
    39         fill(bl,1,2,1,3,4);
    40         for(int i=1;i<=5;++i)for(int j=1;j<=5;++j)ans[i][j]=s[1][1][3][3][i][j]>6?n*n-25+s[1][1][3][3][i][j]:s[1][1][3][3][i][j];//(1,1)
    41         for(int i=4;i<=bl;i+=2)for(int j=2;j<=bl;++j)fill(i,j,3,5,1,2);
    42         for(int i=3;i<=bl;i+=2)for(int j=2;j<=bl;++j)fill(i,j,3,2,1,5);
    43         for(int i=2;i<bl-1;i+=2)fill(2,i,3,3,1,3),fill(1,i,3,3,3,1);
    44         for(int i=3;i<bl;i+=2)fill(2,i,3,3,3,1),fill(1,i,3,3,5,3);
    45         fill(1,bl,5,3,5,1);fill(2,bl,3,5,3,3);fill(2,bl-1,2,4,1,3);fill(1,2,3,3,1,2);fill(1,bl-1,3,3,3,1);
    46     }else{int alc=-2;
    47         for(int i=1;i<=bl;++i)ord[i][1]=++alc;
    48         for(int i=bl;i;--i)if(i&1)for(int j=bl;j>1;--j)ord[i][j]=++alc;
    49             else for(int j=2;j<=bl;++j)ord[i][j]=++alc;
    50         for(int i=2;i<bl;++i)fill(i,1,2,1,5,3);
    51         fill(bl,1,2,1,3,4);
    52         for(int i=1;i<=5;++i)for(int j=1;j<=5;++j)ans[i][j]=s[1][1][3][3][i][j]>6?n*n-25+s[1][1][3][3][i][j]:s[1][1][3][3][i][j];//(1,1)
    53         for(int i=1;i<=bl;i+=2)for(int j=2;j<=bl;++j)fill(i,j,3,5,1,2);
    54         for(int i=2;i<=bl;i+=2)for(int j=2;j<=bl;++j)fill(i,j,3,2,1,5);
    55     }
    56     for(int i=1;i<=n;++i,puts(""))for(int j=1;j<=n;++j)printf("%3d ",ans[i][j]);
    57 }
    View Code
  • 相关阅读:
    STL中关于map和set的四个问题?
    PHP之Zip扩展,解压缩文件,ZipArchive类
    PHP之音乐ID3扩展
    关于PHP执行超时的问题
    PHP中GD库安装
    PHP之输出控制 ob_start(),ob_get_contents(),ob_end_clean()
    PHP之xdebug详解
    PHP上传文件详解
    php使用Header函数,PHP_AUTH_PW和PHP_AUTH_USER做用户验证及缺点
    深入研究php://input与php://output
  • 原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/11664735.html
Copyright © 2011-2022 走看看