9.10 AHSOFNU校内模拟

Posted drizzly

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了9.10 AHSOFNU校内模拟相关的知识,希望对你有一定的参考价值。

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校内模拟的主要内容,如果未能解决你的问题,请参考以下文章

9.24 AHSOFNU 校内模拟

10.25 AHSOFNU 校内模拟

10.27 AHSOFNU 校内模拟(泉七)

9.10模拟赛

校内模拟赛T1大美江湖

2017-9-3 校内模拟T2取数win