1. 程式人生 > >9.10 AHSOFNU校內模擬

9.10 AHSOFNU校內模擬

消息 睡覺 自己 計算 include pen a.out afa pre

9.10完整的在AHSOFNU考了一場模擬賽

以下記錄了本次考試的題目(由於mhm想當然的以為是跳石子而沒有sort就打掛惹T-T)

本次考試被出題人判定為普及-(???)

//以下題目中有貼std代碼,等A後修正為自己代碼

——————————————————————分割線——————————————————————————————————————

T1:

CCT

  最近學校又發了n本五三題霸,BBS看到後十分高興。但是,當他把五三拿到手後才發現,他已經刷過這些書了!他又認真地看了一會兒,發現新發的這些五三是2017版的,而他刷的是2016版的。現在他想找出所有他沒有刷過的題來刷。每本五三都有m道題,並且它的特征(即它和去年版本的五三的差距)可以用一個m位二進制數來代表,二進制位上的1代表該題不同,0代表該題相同。比如4(100)就代表題目3和去年的有不同、5(101)就代表題目1和題目3和去年的有不同。而BBS熱衷於給自己找麻煩,他要選擇連續一段的幾本五三一起刷,並且要求,所有選擇的五三的特征中的所有k位中每一位出現1的次數都相同。他又想去刷最多的書,請你告訴他,他最多能刷多少本書?

輸入格式:

  第一行為兩個整數 n、m,接下來的n行為 n 個整數,表示每本五三的特征。

輸出格式:

  一個整數,表示BBS最多能刷幾本書。

樣例輸入

樣例輸出

7 3

7

6

7

2

1

4

2

4

樣例解釋:

  這7本五三的特征分別為111,110,111,010,001,100,010。選擇第3本至第6本五三,這些五三的特征中每一位都出現了2次1。當然,選擇第4本到第6本也是可以的,這些五三的特征中每一位都出現了1次1。只是這樣子BBS刷的書的數量就少了,他就會不高興。

數據範圍:

  對於 100%的數據:1<=n<=100000,1<=k<=30。

solution://不會打(%%%)

CCT:
  對於一個特征 a1a2a3...am,我們用(a1-a1)(a2-a1)(a3-a1)...(am-a1)來表示它,然後再做對每一 位前綴和(s1-s1)(s2-s1)(s3-s1)...(sm-s1)。易發現,當兩個位置 i、j 前綴和相同時,i+1 到 j 或 i 到 j-1 即是一種可行的選法。用個 set 記住每個前綴和最早出現的位置,對每個位置在 set 中查 詢並更新答案即可。

 1 //這是ditoly的代碼 等我A了就更新自己的代碼
 2 #include <cstdio>
 3 #include <set
> 4 5 int k; 6 struct sth 7 { 8 int num; 9 int dif[30]; 10 bool operator <(const sth &b)const 11 { 12 int i; 13 for(i=1;i<k;i++) 14 { 15 if(dif[i]!=b.dif[i]) return dif[i]<b.dif[i]; 16 } 17 return false; 18 } 19 }t; 20 std::set<sth> s; 21 std::set<sth>::iterator it; 22 int n,x,ans; 23 int sum[100001][31]; 24 25 int max(int a,int b) 26 { 27 return a>b?a:b; 28 } 29 30 int main() 31 { 32 freopen("cct.in","r",stdin); 33 freopen("cct.out","w",stdout); 34 scanf("%d%d",&n,&k); 35 for(int i=1;i<=n;i++) 36 { 37 scanf("%d",&x); 38 for(int j=1;j<=k;j++) 39 { 40 sum[i][j]=sum[i-1][j]; 41 if(x&(1<<(j-1))) sum[i][j]++; 42 } 43 } 44 ans=0; 45 t.num=0; 46 for(int i=1;i<k;i++) t.dif[i]=0; 47 s.insert(t); 48 for(int i=1;i<=n;i++) 49 { 50 t.num=i; 51 for(int j=1;j<k;j++) t.dif[j]=sum[i][j]-sum[i][j+1]; 52 it=s.find(t); 53 if(it==s.end()) s.insert(t); 54 else ans=max(ans,i-(*it).num); 55 } 56 printf("%d",ans); 57 return 0; 58 }

T2:

MHM

   LGL今天一共要上n節課,這n節課由0標號至n。由於過度勞累,除了第0節課和第n節課,LGL還打算睡上m節課,所以他做了一個睡覺計劃表。通過小道消息,LGL得知WQ今天會在學校中檢查,所以他想少睡k節課。但是由於某些原因,他又想使相鄰的兩節睡覺的課之間上的課數量的最小值最大。由於他很困,所以他請你來幫他計算這個值。

輸入格式:

  第一行為三個整數 n、m、k,接下來的m行為m個整數ai,表示睡覺計劃表中LGL想要睡覺的課。

輸出格式:

  一個整數,表示題目所求的值。

樣例輸入

樣例輸出

25 5 2

14

11

17

2

21

3

樣例解釋:

  選擇第2節和第14節不睡覺,這樣子相鄰的兩節睡覺的課之間上的課數量的最小值為3,即第17節和第21節之間和第21節到第25節之間。沒有答案更大的刪除方案。

數據範圍:

  對於100%的數據:1<=n<=1091<=k<=m<=50000,0<ai<n。

solution:

    跳石子原題,連樣例都一樣的(然而我還是打掛了...)

     二分答案判定即可,輸入數據要sort一下,如果copy跳石子的代碼記得sort後的Binsearch()-1...

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 using namespace std;
 5 int a[50001],l,n,m;
 6 int find(int l){
 7     int sum=0,lesson=0;
 8     lesson=m;
 9     for(int i=0;i<=n;i++){
10         sum+=a[i];
11         if(sum<l) lesson--;
12         else sum=0;
13         if(lesson<0) return 0;
14     }
15     return 1;
16 } 
17 int BinSearch(){
18     int left=0,right=l;
19     int mid;
20     while(left<=right){
21         mid=(left+right)/2;
22         if(find(mid)){
23             if(mid+1<=right&&find(mid+1)) left=mid+1;
24             else return mid;
25         }
26         else right=mid-1;
27     }
28     return 0;
29 }
30 int main(){
31     freopen("mhm.in","r",stdin);
32     freopen("mhm.out","w",stdout);
33     int x=0;
34     cin>>l>>n>>m;
35     for(int i=1;i<=n;i++) cin>>a[i];
36     a[0]=0;
37     a[n+1]=l;
38     sort(a,a+n+1);
39     for(int i=0;i<=n;i++) a[i]=a[i+1]-a[i];
40     x=BinSearch()-1;
41     cout<<x<<endl;
42     return 0;
43 }

T3:

AAFA

  YYH有n道題要做。每一道題都有一個截止日期t,只要在該日期之前做完,他的父親LRB就會獎勵他w元錢。令人驚訝的是,每一道題他都只需要1秒來做。請問他最多能從父親那裏拿到多少錢?

輸入格式:

  第一行為一個整數 n,接下來的n行每一行都有兩個數tiwi,分別表示第i題的截止日期和獎勵。

輸出格式:

  一個整數,表示YYH的最大獲利。

樣例輸入

樣例輸出

3

2 10

1 5

1 7

17

樣例解釋:

  第1秒做第3道題,第2秒做第1道題。

數據範圍:

  對於 100%的數據:1<=n、ti wi <=100000。

solution:

   按截止時間排序從頭往後選。選到第 i 個時,若已選擇的題目數量小於 ti,則該時間選 擇它一定更優;若已選擇的數量等於 ti,則比較第 i 題的收益和已選擇的題目中的最小收益, 在酌情選擇。已選擇的題目用優先隊列維護。

  

 1 //依舊是ditoly的代碼
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<queue>
 5 #include<algorithm>
 6 using namespace std;
 7 priority_queue<int> q;
 8 int n;long long ans=0ll;
 9 struct xxx{
10     int t,w;
11 }f[100100];
12 bool cmp(xxx a,xxx b){return a.t>b.t;}
13 int main()
14 {
15     freopen("aafa.in","r",stdin);freopen("aafa.out","w",stdout);
16     scanf("%d",&n);int y=1;
17     for(int i=1;i<=n;i++)scanf("%d%d",&f[i].t,&f[i].w);
18     sort(f+1,f+n+1,cmp);
19     for(int i=100000;i>=1;i--)
20     {
21         while(i==f[y].t){q.push(f[y].w);y++;}
22         if(!q.empty()){ans+=(long long)q.top();q.pop();}
23     }
24     cout<<ans;
25     return 0;
26 }

T4:

ZZI

YYH拿到了父親給的錢欣喜若狂,把這些錢拿來造了n棟房子。現在他要給這些房子通電。他有兩種方法:第一種是在房間裏搭核電發電機發電,對於不同的房子,他需要花不同的代價Vi;,第二種是將有電的房子i的電通過電線通到沒電的房子j中,這樣子他需要花的代價為aij。他現在請你幫他算出他最少要花多少錢才能讓所有的房子通上電。

輸入格式:

  第一行為一個整數 n。接下來的n行為 n 個整數vi,再接下來的n行每行n個數,第i行第j列的數表示aij

輸出格式:

  一個整數,表示最小代價。

樣例輸入

樣例輸出

4
5

4

4

3
0 2 2 2
2 0 3 3
2 3 0 4
2 3 4 0

9

樣例解釋:

  在第4棟房子造核電發電機,再將其他三棟房子通過電線連向它。

數據範圍:

  對於 100%的數據:1<=n<=300,1<=viaij<=100000,保證aii=0,aij=aji

solution:

    應該是一個裸的最小生成樹。要註意可能建核電站比連邊代價小。

    所以可以把建站作為一個新的點加入,直接跑最小生成樹。

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 const int Max_v=305;    
 5 const int INF=0x7fffffff;     
 6 int cost[Max_v][Max_v];        
 7 int mincost[Max_v];        
 8 bool used[Max_v];            
 9 int V;                        
10 int prim(){
11     fill(mincost,mincost+V,INF);         
12     fill(used,used+V,false);
13     mincost[0]=0;
14     int res=0;
15     while(true){
16         int v=-1;
17         for(int u=0;u<V;u++){
18             if(!used[u]&&(v==-1||mincost[u]<mincost[v])) v=u;
19         }
20         if(v==-1) break;
21         used[v]=true;
22         res+=mincost[v];
23         for(int u=0;u<V;u++) 
24             if (cost[v][u])mincost[u]=min(mincost[u],cost[v][u]); 
25     }
26     return res;
27 }
28 int main(){
29     freopen("zzi.in","r",stdin);
30     freopen("zzi.out","w",stdout);
31     scanf("%d",&V);
32     for(int i=0;i<V;i++)
33         scanf("%d",&cost[i][V]),cost[V][i]=cost[i][V];
34     cost[V][V]=0;
35     for(int i=0;i<V;i++)
36       for(int j=0;j<V;j++)
37       scanf("%d",&cost[i][j]);
38     V++;
39     cout<<prim();
40     return 0;
41 }

9.10 AHSOFNU校內模擬