CSP CCF: 201903-3 损坏的RAID5 (C++)90分

题目来源

201903-3 损坏的RAID5

数据特点

在这里插入图片描述

知识点

  1. C++中的异或运算符: ^

  2. C++按位运算符只能与 char 和 int数据类型一起使用

     如或操作:
     int a = 111;    // 0110 1111
     int b = 222;    // 1101 1110
     int c = a | b;    // 1111 1111 
     cout<<c<<endl;
     // 255
    
  3. 加速输入输出

      ios::sync_with_stdio(false); 
      cin.tie(0); 
      cout.tie(0);
    

    参考文章:cin.tie() 输入加速器

  4. printf(“%s”, str); 中 str是字符型数组或指针,不能是string类型。因为在C中没有string类型,所以要用string类对象的成员函数c_str()把string对象转换成C中的字符串样式才能不报错。如:

     string str;
     printf("%s", str.c_str());
    

20 分

运行错误
是以拿满分的思路出发的,但只拿了20分。

#include <iostream>
#include <fstream>
#include <map>
#include <vector>

using namespace std;


const int baselen = 8;  // 一块所需的字符数
map<char, int> s2t = {
    {'0', 0}, {'1', 1}, {'2', 2}, {'3', 3}, {'4', 4}, {'5', 5}, {'6', 6}, {'7', 7}, {'8', 8}, {'9', 9},
    {'A', 10}, {'B', 11}, {'C', 12}, {'D', 13}, {'E', 14}, {'F', 15}
    };
map<int, char> t2s = {
    {0, '0'}, {1, '1'}, {2, '2'}, {3, '3'}, {4, '4'}, {5, '5'}, {6, '6'}, {7, '7'}, {8, '8'}, {9, '9'},
    {10, 'A'}, {11, 'B'}, {12, 'C'}, {13, 'D'}, {14, 'E'}, {15, 'F'}
    };

int N, S, L;
vector<int> disk[1001];


void calculateOther(int restIndex) {
    bool isinit = false;  // 未输入的那一列是否已初始化

    for (int i = 0; i < N; ++i) {
        // 当前下标与未的一样
        if (i == restIndex) {
            continue;
        }

        // 未初始化
        if (!isinit) {
            isinit = true;
            for (int j = 0; j < disk[i].size(); ++j) {
                disk[restIndex].push_back(disk[i][j]);
            }
        }
        // 已初始化
        else {
            for (int j = 0; j < disk[i].size(); ++j) {
                disk[restIndex][j] ^= disk[i][j];  // 异或操作
            }
        }
    }
}

int main() {
    ifstream cin("in2.txt");

    cin>>N>>S>>L;  // L== N or L == N - 1

    bool inp[1001] = {false};
    for (int i = 0; i < L; ++i) {
        int index;
        string str;
        cin>>index>>str;

        inp[index] = true;
        for (char c: str) {
            disk[index].push_back(s2t[c]);
        }
    }


    // 缺失数据, 补全数据
    if (N > L) {
        // 获取缺失 硬盘编号
        int restIndex;
        for (int i = 0; i < N; ++i) {
            if (inp[i] == false) {
                restIndex = i;
                break;
            }
        }

        calculateOther(restIndex);  // 根据已有数据补全缺失数据
    }
    // 未缺失数据, 不用处理
    else {}

    // 返回读取的数据
    int M;
    cin>>M;
    for (int i = 0; i < M; ++i) {
        int num;
        cin>>num;

        int X, Y;
        Y = (num / S) % N;  // 硬盘编号
        X = (num / ((N - 1) * S)) * S +  (num % S);

        for (int x = X * baselen; x < (X + 1) * baselen; ++x) {
            cout<<t2s[disk[Y][x]];
        }
        cout<<endl;
    }

    return 0;
}

30分

运行超时
在20分的基础上,看了下输出要求的那一段文字(之前没注意到),按那两个条件弄了一下。加了十分。

#include <iostream>
#include <fstream>
#include <map>
#include <vector>

using namespace std;


const int baselen = 8;  // 一块所需的字符数
map<char, int> s2t = {
    {'0', 0}, {'1', 1}, {'2', 2}, {'3', 3}, {'4', 4}, {'5', 5}, {'6', 6}, {'7', 7}, {'8', 8}, {'9', 9},
    {'A', 10}, {'B', 11}, {'C', 12}, {'D', 13}, {'E', 14}, {'F', 15}
    };
map<int, char> t2s = {
    {0, '0'}, {1, '1'}, {2, '2'}, {3, '3'}, {4, '4'}, {5, '5'}, {6, '6'}, {7, '7'}, {8, '8'}, {9, '9'},
    {10, 'A'}, {11, 'B'}, {12, 'C'}, {13, 'D'}, {14, 'E'}, {15, 'F'}
    };

int N, S, L;
vector<int> disk[1001];


void calculateOther(int restIndex) {
    bool isinit = false;  // 未输入的那一列是否已初始化

    for (int i = 0; i < N; ++i) {
        // 当前下标与未输入的一样
        if (i == restIndex) {
            continue;
        }

        // 未初始化
        if (!isinit) {
            isinit = true;
            for (long long int j = 0; j < disk[i].size(); ++j) {
                disk[restIndex].push_back(disk[i][j]);
            }
        }
        // 已初始化
        else {
            for (long long int j = 0; j < disk[i].size(); ++j) {
                disk[restIndex][j] ^= disk[i][j];  // 异或操作
            }
        }
    }

    /* // 输出被填补的那个盘
    for (int i = 0; i < disk[restIndex].size(); ++i) {
        cout<<t2s[disk[restIndex][i]];
    }
    cout<<endl;
    */
}

int main() {
    ifstream cin("in.txt");

    cin>>N>>S>>L;  // L== N or L == N - 1

    bool inp[1001] = {false};
    for (int i = 0; i < L; ++i) {
        int index;
        string str;
        cin>>index>>str;

        inp[index] = true;
        for (char c: str) {
            disk[index].push_back(s2t[c]);
        }
    }


    // 缺失数据, 补全数据
    if (N == L + 1) {
        // 获取缺失 硬盘编号
        int restIndex;
        for (int i = 0; i < N; ++i) {
            if (inp[i] == false) {
                restIndex = i;
                break;
            }
        }

        calculateOther(restIndex);  // 根据已有数据补全缺失数据
    }
    // 未缺失数据, 不用处理
    else {}

    // 返回读取的数据
    int M;
    cin>>M;
    for (int i = 0; i < M; ++i) {
        long long int num;
        cin>>num;

        if (num <(long long int)(N-1) * (disk[0].size() / baselen) ) {  // num在范围内
            long long X, Y;
            Y = (num / S) % N;  // 硬盘编号
            X = (num / ((N - 1) * S)) * S +  (num % S);
            if (inp[N] == false && N > (long long int)(L + 1)) {  // 缺失数据过多
                cout<<"-"<<endl;
            }
            else {
                for (int x = X * baselen; x < (X + 1) * baselen; ++x) {
                    //cout<<Y<<" "<<x<<endl;
                    cout<<t2s[disk[Y][x]];
                }
                cout<<endl;
            }
        }
        else {
            cout<<"-"<<endl;
        }

    }

    return 0;
}

70分

运行超时

  1. 添加了 ios::sync_with_stdio(false); 来加速输入的读取。
  2. main函数中的 if (inp[N] == false && N > (L + 1)) { // 缺失数据过多, 并且问的缺失的数据 中 inp[N] 改为 inp[Y]。
  3. 其余无变化。

90分

运行超时

  1. 修改了 存储硬盘数据的数据结构。由整型矩阵变为字符型矩阵。
  2. 其余基本无变化。
#include <iostream>
#include <fstream>
#include <map>
#include <vector>

using namespace std;


const int baselen = 8;  // 一块所需的字符数
map<char, int> s2t = {
    {'0', 0}, {'1', 1}, {'2', 2}, {'3', 3}, {'4', 4}, {'5', 5}, {'6', 6}, {'7', 7}, {'8', 8}, {'9', 9},
    {'A', 10}, {'B', 11}, {'C', 12}, {'D', 13}, {'E', 14}, {'F', 15}
    };
map<int, char> t2s = {
    {0, '0'}, {1, '1'}, {2, '2'}, {3, '3'}, {4, '4'}, {5, '5'}, {6, '6'}, {7, '7'}, {8, '8'}, {9, '9'},
    {10, 'A'}, {11, 'B'}, {12, 'C'}, {13, 'D'}, {14, 'E'}, {15, 'F'}
    };

int N, S, L;
//vector<int> disk[1001];
string input[1001];         // 存储输入的数据
bool inp[1001] = {false};   // 记录该硬盘有输入数据

void calculateOther() {
    // 获取缺失 硬盘编号
    int restIndex;
    for (int i = 0; i < N; ++i) {
        if (inp[i] == false) {
            restIndex = i;
            break;
        }
    }

    bool isinit = false;  // 未输入的那一列是否已初始化

    for (int i = 0; i < N; ++i) {
        // 当前下标与未输入的一样
        if (i == restIndex) {
            continue;
        }

        // 未初始化
        if (!isinit) {
            isinit = true;
            input[restIndex] = input[i];  // 先复制过来
        }
        // 已初始化
        else {
            for (long long int j = 0; j < input[i].size(); ++j) {
                int t1 = s2t[input[restIndex][j]], t2 = s2t[input[i][j]];
                int t3 = t1 ^ t2;
                input[restIndex][j] = t2s[t3];  // 异或操作
            }
        }
    }

    /* // 输出被填补的那个盘
    for (int i = 0; i < disk[restIndex].size(); ++i) {
        cout<<t2s[disk[restIndex][i]];
    }
    cout<<endl;
    */
}

int main() {
    ios::sync_with_stdio(false);   //  加速输入

    ifstream cin("in2.txt");



    // 输入数据
    cin>>N>>S>>L;  // L== N or L == N - 1
    for (int i = 0; i < L; ++i) {
        int index;
        string str;
        cin>>index;
        cin>>input[index];

        inp[index] = true;
    }

    // 缺失一个盘的数据,则补全数据
    if (N == L + 1) {
        calculateOther();  // 根据已有数据补全缺失数据
    }
    // 未缺失数据 或者缺失数据过多, 不用处理
    else {}

    // 返回读取的数据
    int M;
    cin>>M;
    for (int i = 0; i < M; ++i) {
        long long int num;
        cin>>num;

        if (num < (long long int)(N-1) * (input[0].size() / baselen) ) {  // num在范围内
            long long X, Y;
            Y = (num / S) % N;  // 硬盘编号
            X = (num / ((N - 1) * S)) * S +  (num % S);  // 字符下标
            if (inp[Y] == false && N > (L + 1)) {  // 缺失数据过多, 并且问的缺失的数据
                cout<<"-"<<endl;
            }
            else {
                for (int x = X * baselen; x < (X + 1) * baselen; ++x) {
                    //cout<<Y<<" "<<x<<endl;
                    cout<<input[Y][x];
                }
                cout<<endl;
            }
        }
        else {
            cout<<"-"<<endl;
        }

    }

    return 0;
}

求解

怎样能提高至100分?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值