题目链接:戳这里
题意:
有n个硬盘,把n个硬盘分成许多个条带,每个条带含有s个块,按照 RAID5 的规则,即每一行的条带中都会有一个条带负责校验,它的值是其他条带的异或和。把数据存放在n个硬盘中,求第temp块上存储的数据。
注意:最大的数据长度为40KB,数据中每两个字符组成一个字节,因此数组需要开到80000。
这题题意很难读,好在第二个样例给出了图,可以对着那个图模拟。
下面本人ac代码,很多地方写的都挺麻烦。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <map>
#include <stack>
using namespace std;
const int maxn = 1e3 + 10;
char st[maxn][80000+5];
bool vis[maxn];
int main() {
int n, s, l, m, len;
scanf("%d %d %d", &n, &s, &l);
int temp = -1;
for(int i = 0; i < l; ++i) {
scanf("%d ", &temp);
fgets(st[temp],85000,stdin);
vis[temp] = 1;
}
len = strlen(st[temp]);
scanf("%d", &m);
while(m--) {
int row = 1, col = 0;
scanf("%d", &temp);
if(temp >= (len / 8) * (n-1) ) {//如果超出范围,直接输出
puts("-"); continue;
}
while(row * (n-1) * s <= temp) {//判断在哪一行
++row;
}
--row;
col = ((n - row) + (temp - row * (n - 1) * s) / s) % n;//判断在哪个磁盘
int offset = (temp - row * (n - 1) * s) % s;//判断在磁盘的具体那一部分
int block = row * s + offset;
if(vis[col]) {
for(int i = 0; i < 8; ++i) {
printf("%c", st[col][i + block * 8]);
}
printf("\n");
} else if(n - l == 1){
for(int i = 0; i < 8; ++i) {
int ans = 0;
char c;
for(int j = 0; j < n; ++j) {
if(j == col) continue;
c = st[j][i + block * 8];
if(c >= '0' && c <= '9') ans ^= int(c -'0');
else ans ^= int(c - 'A') + 10;
// printf("1ans : %d\n", ans);
}
if(ans > 9) printf("%c", char('A'+ans - 10));
else printf("%c", char(ans+'0'));
}
printf("\n");
} else {
puts("-");
}
}
return 0;
}
/*
2 1 2
0 000102030405060710111213141516172021222324252627
1 000102030405060710111213141516172021222324252627
3
0
1
2
3 2 2
0 000102030405060710111213141516172021222324252627
1 A0A1A2A3A4A5A6A7B0B1B2B3B4B5B6B7C0C1C2C3C4C5C6C7
13
0
1
2
3
4
5
6
7
8
9
10
11
12
3 2 1
0 000102030405060710111213141516172021222324252627
3
0
1
2
4 2 2
0 000102030405060710111213141516172021222324252627
1 A0A1A2A3A4A5A6A7B0B1B2B3B4B5B6B7C0C1C2C3C4C5C6C7
13
0
1
2
3
4
5
6
7
8
9
10
11
12
*/
在对 该博客 进行学习后,对本人代码进行改进得:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <map>
#include <stack>
using namespace std;
const int maxn = 1e3 + 10;
char st[maxn][80000+5];
bool vis[maxn];
int main() {
int n, s, l, m, len;
scanf("%d %d %d", &n, &s, &l);
int temp = -1;
for(int i = 0; i < l; ++i) {
scanf("%d ", &temp);
fgets(st[temp],85000,stdin);
vis[temp] = 1;
}
len = strlen(st[temp]);
scanf("%d", &m);
while(m--) {
int row = 1, col = 0;
scanf("%d", &temp);
if(temp >= (len / 8) * (n-1)) {//如果超出范围,直接输出
puts("-"); continue;
}
int band = temp / s;//条带号
row = band / (n - 1);//磁盘的某一个条带
col = ((n - row) + (temp - row * (n - 1) * s) / s) % n;//判断在哪个磁盘
int offset = temp % s;//条带的具体那一块
int block = row * s + offset; //磁盘的具体那一块
if(vis[col]) {
for(int i = 0; i < 8; ++i) {
printf("%c", st[col][i + block * 8]);
}
printf("\n");
} else if(n - l == 1){
for(int i = 0; i < 8; ++i) {
int ans = 0;
char c;
for(int j = 0; j < n; ++j) {
if(j == col) continue;
c = st[j][i + block * 8];
if(c >= '0' && c <= '9') ans ^= int(c -'0');
else ans ^= int(c - 'A') + 10;
// printf("1ans : %d\n", ans);
}
if(ans > 9) printf("%c", char('A'+ans - 10));
else printf("%c", char(ans+'0'));
}
printf("\n");
} else {
puts("-");
}
}
return 0;
}
本文介绍了一种基于RAID5的数据恢复算法,通过将硬盘分为多个条带,每个条带包含校验位,实现数据冗余。文章详细解析了算法流程,并提供了AC代码示例,适用于最大40KB数据长度的场景。

474

被折叠的 条评论
为什么被折叠?



