201903-3 CSP认证 损坏的RAID5 (超详细解析-小模拟)100分

       这个题还是CSP第三题的老样子,特别难读。

题目简述:

       他讲的是啊,现在有那么一个RAID系统,这个系统有n块硬盘(0 ~ n-1),每块硬盘都要分块(学过操作系统的话应该都知道),一块是4个字节,然后呢有一些原因,他引入了一个叫做条带的东西。然后询问m次,让输出对应物理块的内容。其中可能丢了几块硬盘。

大小关系:

                        RAID系统     >      硬盘        >       条带      >      块

                          (即,一个系统由多个硬盘组成,一个硬盘由多个条带组成,一个条带由多个块组成。)

     什么是条带?

        刚刚不是说每个硬盘分块了吗,然后从0开始标号,这个条带就是连续的多个块,比如说一个条带是2块,那么0号条带就是这个硬盘的0 ~ 7字节,1号条带就是8 ~ 15字节 (每个条带两块,所以一个条带8字节)。

     什么是冗余备份条带?

       就是刚刚不是说n个硬盘吗,那么他们分别都有0号条带,1号条带,2号条带  。。。

       对吧,所以现在有n个0号条带,这n个0号条带中,有n-1个是用来存储数据的,另外的那一个是用来冗余备份的,怎么冗余备份呢,就是其余n-1个的0号条带异或和。

       同理,n个1号条带中也有n-1个存储数据,1个备份

       然后,对于n个x号条带,具体哪个盘的x号条带作为冗余备份呢?他是这样规定的,首先第n号盘的做,然后n-1做,。。。然后0号盘做,然后n号盘的做。可以根据下图理解。红色的就是冗余条带。(这个图没划分块,每个格子是一个条带)

                                        

      询问中硬盘的块号怎么确定?

         这个问题的话最好还是看第2个样例的图,编号是从选中的冗余盘,往后依次填写编号的。

         这个图不同于上边那个,这个虚线部分就是条带内的分块情况。

扫描二维码关注公众号,回复: 11534992 查看本文章

                                                                  

     丢失硬盘怎么办?

             通过异或的性质(1.交换律,2. 相同数异或结果为0)可以得知,如果系统丢失了一个盘,那么可以通过其他盘的异或得出来这块盘,如果少两个盘及以上,就没办法了。

     如何查询?

                  首先输入了块号 q 之后,我们可以得知当前他所属的条带号,假设条带大小为s。

                  所属条带号 tid = q/s;

                  那么这个条带是该硬盘的第几号条带呢 ,通俗来说他在这个图中的哪一行呢?

                 hang = 条带号 /(n-1);              也就是tid / (n-1)

                  现在就是确定他在哪个盘了对吧,我们需要先计算出来冗余盘是哪个

                  很明显 冗余盘 rid = (n-1) - (行%n);

                  是哪块硬盘就是rid往后数 条带号%(n-1)+1个

                  bid = rid +(条带号%(n-1)+1);

                   那么这个再知道这个块在条带内往后偏移了多少就可以了,也就是q%s  。 

                 (注意:如果是唯一缺失的盘。要从其他盘的异或结果得到)

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll MAXN = 1005;
string C[MAXN];
int vis[MAXN],n,s,l,len;
int Xor(int now,int c)
{
    if(c>='0' && c<='9')c -= '0';
    if(c>='A' && c<='Z')c -= 'A',c+=10;
    return now^c;
}
char itoc(int now)
{
    if(now >= 0 && now<=9)now+='0';
    if(now >= 10 && now<=15)now-=10,now+='A';
    return (char)now;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n>>s>>l;
    for(int i=0;i<n;i++)C[i] = "";
    for(int i=1;i<=l;i++){
        int id;
        cin>>id; vis[id] = 1;
        cin>>C[id];
        if(len == 0)len = C[id].size();
    }
    int dis = 0,dis_cnt = 0;
    for(int i=0;i<n;i++){
        if(!vis[i]){
            dis = i; dis_cnt ++;
        }
    }
    int m;
    cin>>m;
    while(m--)
    {
        int q;
        cin>>q;
        int tid = q/s;
        int hang = tid/(n-1);
        int rid = (n-1)-(hang%n);
        int bid = (rid + (tid%(n-1)) + 1)%n;
        int off = q%s;
        int st_add = hang*s*8;
        st_add += off*8;
        if( (dis_cnt >1&&!vis[bid]) || (st_add>=len) ){
            cout<<"-\n";
            continue;
        }
        if(bid == dis){
            string pri = "";
            for(int i=st_add;i<st_add+8;i++){
                int now = 0;
                for(int j = 0;j<n;j++){
                    if(j == dis)continue;
                    now = Xor(now,C[j][i]);
                }
                pri += char(itoc(now));
            }
            cout<<pri<<endl;
            continue;
        }
        for(int i=st_add;i<st_add+8;i++){
            cout<<C[bid][i];
        }
        cout<<"\n";
    }
}
/*
2 1 2
0 000102030405060710111213141516172021222324252627
1 000102030405060710111213141516172021222324252627
2
0
1

3 2 2
0 000102030405060710111213141516172021222324252627
1 A0A1A2A3A4A5A6A7B0B1B2B3B4B5B6B7C0C1C2C3C4C5C6C7
2
2
5
*/

猜你喜欢

转载自blog.csdn.net/qq_41645482/article/details/104298015
今日推荐