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)是塊所在硬盤相對校驗盤的偏移量。(這是先前的版本,對的,但是很復雜。。。后來發現其實可以很簡單,直接 t=b/s%n; 就出來了)

 

一開始我輸入語句是這樣寫的:

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 }
View Code

 

但是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=b/s%n,k=(b/s/(n-1)*s+b%s)*8;
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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM