ccf 201903-3 损坏的RAID5
Posted zbhfz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ccf 201903-3 损坏的RAID5相关的知识,希望对你有一定的参考价值。
9月份考ccf,暑假打算做一些往年的真题。。。
这个题,一开始真是把我给看晕了
传说中的大模拟,果然不简单QAQ
首先读懂题目就是一个大难点,特别是对于我这种题目一长就看不进去的人来说
读懂题目之后,思路就好想了,下面简单说一下我的思路:
首先定义一个字符数组ss[N][M],然后用ss[i]存入编号为 i 的硬盘后面的字符串,
在后面处理的时候就可以用sscanf函数直接获取ss[i]中相应位置的十六进制数(输入用"%8x",输出用"%08X")。
再一个比较烧脑的地方就是根据输入的块的编号b确定该块所在的硬盘和条带编号
条带编号k=b/s/(n-1); 结合图从左到右读这个式子就能想明白
所在硬盘编号t=n-1+k*(n-1)+b/s%(n-1)+1; t%=n; 其中n-1是条带编号为0对应的校验盘位置,条带编号+1,校验盘-1(等价于+(n-1)); b/s%(n-1)是块所在硬盘相对校验盘的偏移量。
一开始我输入语句是这样写的:
1 for(int i=0;i<l;i++) 2 int x; 3 scanf("%d",&x); 4 scanf("%s",ss[x]); 5
然后就是各种超时,哪怕我想方设法优化代码,怎么搞也只有70分
我就纳闷了,这时间复杂度我满打满算也不过1e7啊,咋就超时了呢?
百思不得其解,于是毅然百度。。。
然后发现很多几个题解都是用的很c++风格的代码,算法复杂度和我没什么区别,而且用的cin,居然还比scanf快???
于是乎,我发现了一条神奇的代码
1 ios::sync_with_stdio(false);
据说它可以关闭c++的流同步,防止cin超时
于是乎,我试着把所有的标准输入换成了cin,加上那句我看不懂的玩意儿,居然还真过了!!!
1 #include<cstdio> 2 #include<algorithm> 3 #include<iostream> 4 using namespace std; 5 typedef long long ll; 6 const int M=10240*8+1; 7 const int N=1000; 8 char ss[N][M]; 9 int main() 10 11 //freopen("in.txt","r",stdin); 12 ios::sync_with_stdio(false); 13 int n,s,l; 14 cin>>n>>s>>l;//scanf("%d%d%d",&n,&s,&l); 15 for(int i=0;i<l;i++) 16 int x; 17 cin>>x;//scanf("%d",&x); 18 cin>>ss[x];//scanf("%s",ss[x]); 19 20 int m; 21 cin>>m;//scanf("%d",&m); 22 while(m--) 23 ll b; 24 cin>>b;//scanf("%lld",&b); 25 ll t=n-1+b/s/(n-1)*(n-1)+b/s%(n-1)+1,k=(b/s/(n-1)*s+b%s)*8;t%=n; 26 if(k>=M||ss[t][0]==0&&l<n-1||ss[0][k]==0&&ss[1][k]==0&&ss[t][k]==0) 27 printf("-\n"); 28 continue; 29 30 if(ss[t][0]==0) 31 ll ans=0; 32 for(int i=0;i<n;i++) 33 if(i==t)continue; 34 ll x; 35 sscanf(ss[i]+k,"%8x",&x); 36 ans^=x; 37 38 printf("%08X\n",ans); 39 40 else 41 ll ans; 42 sscanf(ss[t]+k,"%8x",&ans); 43 printf("%08X\n",ans); 44 45 46 return 0; 47
但是scanf超时超在哪呢???
直到之后又看到一篇博客,我才知道字符串输入用scanf会超时,因为最后三组数据40kb的数据长度,意味着一个字符串最多有80kb个字符要输入,而一次最多有1000个字符串待输入,输入数据量贼大
于是改用专门的字符串输入函数gets或fgets就没问题了(不过据说gets大势已去,建议尽量用fgets)
1 #include<cstdio> 2 #include<algorithm> 3 #include<iostream> 4 using namespace std; 5 typedef long long ll; 6 const int M=10240*8+1; 7 const int N=1000; 8 char ss[N][M]; 9 int main() 10 11 //freopen("in.txt","r",stdin); 12 int n,s,l; 13 scanf("%d%d%d",&n,&s,&l); 14 for(int i=0;i<l;i++) 15 int x; 16 scanf("%d%*c",&x); 17 fgets(ss[x],M,stdin);//gets(ss[x]); 18 19 int m; 20 scanf("%d",&m); 21 while(m--) 22 ll b; 23 scanf("%lld",&b); 24 ll t=n-1+b/s/(n-1)*(n-1)+b/s%(n-1)+1,k=(b/s/(n-1)*s+b%s)*8;t%=n; 25 if(k>=M||ss[t][0]==0&&l<n-1||ss[0][k]==0&&ss[1][k]==0&&ss[t][k]==0) 26 printf("-\n"); 27 continue; 28 29 if(ss[t][0]==0) 30 ll ans=0; 31 for(int i=0;i<n;i++) 32 if(i==t)continue; 33 ll x; 34 sscanf(ss[i]+k,"%8x",&x); 35 ans^=x; 36 37 printf("%08X\n",ans); 38 39 else 40 ll ans; 41 sscanf(ss[t]+k,"%8x",&ans); 42 printf("%08X\n",ans); 43 44 45 return 0; 46
以上是关于ccf 201903-3 损坏的RAID5的主要内容,如果未能解决你的问题,请参考以下文章
EMC FC AX-4存储崩溃,raid5硬盘损坏的数据恢复过程
HIS医院信息系统主服务器RAID5崩溃 硬盘损坏 SQL数据库损坏修复 SQL SERVER数据库修复 备份文件无法还原数据恢复