CCFCSP 201903-3 损坏的RAID5

思路

  • 老大模拟题了,但如果仔细阅读题意拿到70分难度并不大,如果做一定的简单优化就可以100分
  • 主要时间复杂度在cout输出(不写 ios::sync_with_stdio(false); 只能拿到30分)和查找属于第几个盘第几块上,下面附上了循环方法(70分)和非循环纯找规律法(100分)供大家参考
    • 循环法就不多说了,遍历每个盘,是p就跳过,不是p就继续直到找到该位置。
    • 非循环法则是寻求规律先找到每个盘的首位置
      • 先不考虑P,第一个条带就是start,start+1 … start+l,那么 某位置%(条带长度*盘数量)就是它对应的第一个条带的相应位置,第一个条带相应位置%条带长度 就是它在该条带中处于第几个块,相减就可以得到首位置。即可得到对应盘位置。
      • 随后根据起始位置得到其在无P情况下处于第几大条带。然后计算在其之前P的数量,每 盘数-1 就有一个P带,第一个P带在,盘数-当前盘(0开始计数),最后即可得到P带数量。
  • 关于异或,直接使用16进制转10进制然后使用^,再返回10进制数以16进制输出即可。

代码

#include <iostream>
#include <vector>
#include <string>
#include <math.h>

typedef long long LL;
using namespace std;

//70分
pair<int,int> forfind(int Dsk,int l,int totl,int thenum){
    pair<int,int> res;
    res.first=-1;
    res.second=-1;
    for(int i=0;i<Dsk;i++){
        int nownum=i*l;
        vector<int> temp;
        for(int j=0;j<totl;j+=l){
            int block=j/l;
            if(block%Dsk!=Dsk-i-1){
                for(int k=0;k<l;k++){
                    if(nownum+k==thenum){
                        res.first=i;
                        res.second=j+k;
                        break;
                    }
                }
                if(res.first!=-1)
                    break;
                nownum+=Dsk*l;
            }
        }
        
        if(res.first!=-1)
            break;
    }
    return res;
}

//100分
pair<int,int> find(int Dsk,int l,int totl,int thenum){
    pair<int,int> res;
    res.first=-1;
    res.second=-1;
    
    int t=Dsk*l;
    int start=(thenum%t)-(thenum%t)%l;//该盘开始位置,从0开始
    res.first=start/l;//处于第几个盘,从0开始
    int block=(thenum-start)/t+1;//第几个条带,从1开始
    int blockp=(block-(Dsk-res.first))/(Dsk-1);//前面有几个P条带,从1开始
    if((block-(Dsk-res.first))<0)
        blockp=0;
    else
        blockp+=1;

    block+=blockp;
    res.second=(block-1)*l+(thenum-start)%t;
    if(res.second>=totl)
        res.second=-1;

    return res;
}

LL count(vector<string> list){
    LL res=0;
    for(int i=0;i<list.size();i++){
        string temp=list[i];
        
        LL nowres=0;
        for(int j=0;j<temp.length();j++){
            LL te=0;
            if(temp[j]>='A'&&temp[j]<='F'){
                te=temp[j]-'A'+10;
            }
            else{
                te=temp[j]-'0';
            }
            //nowres+=nowres*16+te;
            nowres+=te*pow(16,temp.length()-j-1);
        }
        //cout<<temp<<" "<<nowres<<endl;
        if(i==0)
            res=nowres;
        else{
            res=res^nowres;
        }
        
    }
    
    //cout<<res<<endl;

    return res;
}

int main(){
    ios::sync_with_stdio(false);//不加只能拿到30分
    int n=0,l=0,in=0;
    cin>>n>>l>>in;
    string save[1005]={""};

    for(int i=0;i<in;i++){
        int nowl=0;
        cin>>nowl;
        //cout<<nowl<<endl;
        cin>>save[nowl];

    }
    
    int totl=save[0].length()/8;
    
    int m=0;
    cin>>m;
    for(int i=0;i<m;i++){
        int search=0;
        cin>>search;
        
        pair<int,int> pos=find(n,l,totl,search);
            
        if(pos.first==-1 || pos.second==-1){
            cout<<"-"<<endl;
            continue;
        }
        
        if(save[pos.first]==""){
            vector<string> input;
            int error=0;
            for(int j=0;j<n;j++){
                if(j!=pos.first && save[j]!=""){
                    string temp=save[j].substr(8*pos.second,8);
                    input.push_back(temp);
                }
                if(save[j]==""){
                    error++;
                }
                
            }

            if(error>1){
                cout<<"-"<<endl;
                continue;
            }
            else{
                LL res=count(input);
               
                printf("%08X\n",res);
            }
        }
        else{
            string temp=save[pos.first].substr(8*pos.second,8);
            cout<<temp<<endl;
        }
    }
    return 0;
}

/*
2 1 2
0 000102030405060710111213141516172021222324252627
1 000102030405060710111213141516172021222324252627
2
0
1
*/

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值