10.25 AHSOFNU 校内模拟
Posted drizzly
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了10.25 AHSOFNU 校内模拟相关的知识,希望对你有一定的参考价值。
//今天泉七考我们的题 感觉大家都很巨大啊~
切题(problem)
【问题描述】
小 Z 和小 G 都是切题好手,他们经常抢着切题,今天他们已经 决定好了 n 道要切的题目并准备按照顺序切掉这些题。每道题都有一个难度值 di,两个人都想自己切掉的题难度值之和最大,但他们又不屑于切对方切过的题,于是两人制定了如下规则:一开始,决定谁切下一道题的权利在作为老大的小 Z 手里,拥有这个权利的人可以指定谁切下一道题,当被指定的那个人切完题后,这个权利会转移到没切这道题的那个人手上(可以是自己)。两人都很强,所以他们总是进行最优的决策以使自己切到的题难度值之和最大。F 大爷想知道他们最后各自切的题的难度值之和。
【输入格式】
第一行一个正整数 n,表示题数。
接下来 n 个正整数 di,依次表示第 i 道要切的题的难度值。
【输出格式】
输出两个用空格隔开的整数,分别表示小 Z 和小 G 切掉的题的难度值之和。
【样例输入】
4
2 3 3 3
【样例输出】
6 5
【数据范围】
对于 20%的数据,n<=5;
对于 40%的数据,n<=50;
对于 60%的数据,n<=500;
对于 80%的数据,n<=5000;
对于 100%的数据,n<=50000,di<=100。
Solution:
由于权利在小 Z 或小 G 手上,而且转移只有取与不取,我们可以考虑DP。
每个状态向后转移只有两种,我们可以倒着DP,dp[ i ] [0/1]表示还剩下 i 道题,考虑小 Z 之后的收益之和,所以小 Z 会对两者去max,小 G 会对两者取min。
1 #include<cstdio> 2 #define MAXN 50005 3 using namespace std; 4 int f[2][MAXN],d[MAXN],sum=0; 5 inline int Max(int a,int b){return a>b?a:b;} 6 inline int Min(int a,int b){return a<b?a:b;} 7 int main(){ 8 freopen("problem.in","r",stdin); 9 freopen("problem.out","w",stdout); 10 int n;scanf("%d",&n); 11 for(int i=1;i<=n;i++) scanf("%d",&d[i]),sum+=d[i]; 12 for(int i=n;i>=1;i--) { 13 f[0][i]=Max(f[0][i+1],f[1][i+1]+d[i]);//small Z 14 f[1][i]=Min(f[0][i+1],f[1][i+1]+d[i]);//small G 15 } 16 printf("%d %d",f[0][1],sum-f[0][1]); 17 return 0; 18 }
开车(car)
【问题描述】
老司机小 Q 要在一个十字路口指挥车队开车,这个十字路口可 以描述为一个 n*n 的矩阵,其中第 2 行到第 n-1 行都各有一道横向车 道,第 2 列到第 n-1 列都各有一条纵向车道。飙车开始前,小 Q 可以 在每条车道的两端(横向车道为从左到右第 1 格和第 n 格,纵向车道 为从上到下的第 1 格和第 n 格)安置一辆大卡车。安置结束后,小 Q可以下令让所有大卡车同时向车道的另一端行驶,所有的卡车速度都相同。小 Q 要合理安排这些卡车,使得它们在行驶过程中不会相撞;另外一些格子上有小 C 放置的巨石,这些格子不能通过卡车。小 Q希望安置的卡车最多,请你求出最多的卡车数。
【输入格式】
第一行两个非负整数 n 和 m,分别表示十字路口大小和巨石数量。
接下来 m 行,每行两个正整数 xi,yi,表示在第 xi 行第 yi 列有一个巨石。
【输出格式】
输出一个整数,表示答案。
【样例输入】
4 3
3 1
3 2
3 3
【样例输出】
1
【数据范围】
对于 20%的数据,n<=5;
对于 40%的数据,n<=10;
对于 70%的数据,n<=1000;
对于 100%的数据,3<=n<=200000,m<=200000。
Solution:
由于存不存在可能,无论行列都只与 n-i+1 有关,暴力枚举即可。
1 #include<cstdio> 2 #include<cstring> 3 #define MAXN 200005 4 #define debug 0 5 using namespace std; 6 int n,m,ans=0; 7 bool a[MAXN][2]; 8 int main(){ 9 freopen("car.in","r",stdin); 10 freopen("car.out","w",stdout); 11 scanf("%d%d",&n,&m); 12 memset(a,true,sizeof(a)); 13 while(m--){ 14 int x,y;scanf("%d%d",&x,&y); 15 a[x][0]=false;a[y][1]=false; 16 } 17 #if debug 18 for(int i=1;i<=n;i++) printf("%d ",a[i][0]);printf("its 0\n"); 19 for(int i=1;i<=n;i++) printf("%d ",a[i][1]);printf("its 1\n"); 20 #endif 21 for(int i=2;i<=n-1;i++){ 22 if(a[i][0]==true) ans++; 23 if(a[i][1]==true) ans++; 24 } 25 if(n&1) if(a[n/2+1][0]&&a[n/2+1][1]) ans--; 26 printf("%d",ans); 27 return 0; 28 }
学习(study)
【问题描述】
巨弱小 D 准备学习,有 n 份学习资料给他看,每份学习资料的 内容可以用一个正整数 ai 表示。小 D 如果在一天内学习了多份资料,他只能记住这些资料的内容表示成的整数的最大公约数的部分。学习若干份资料得到的收益是小 D 记下的内容之和,也就是学习的资料 数乘上这些资料内容的最大公约数。小 D 今天准备挑一段连续的资料来学习,请你告诉他最大的收益是多少。
【输入格式】
第一行一个正整数 n,表示资料数。
接下来 n 个正整数 ai,分别表示每份资料的内容。
【输出格式】
输出一个整数,表示答案。
【样例输入】
5
30 60 20 20 20
【样例输出】
80
【数据范围】
对于 20%的数据,n<=100;
对于 40%的数据,n<=1000;
对于 70%的数据,n<=100000;
对于 100%的数据,n<=500000,ai<=10^9。
Solution:
对于每个右端点,其对应的区间的gcd只有log种(gcd每次变小必然会少一个质因子,而一个数的质因子只有log个),从左向右推的同时维护每种gcd的左端点即可。
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 #define MN 500000 5 int gcd(int x,int y){return y?gcd(y,x%y):x;} 6 int a[MN+5],p[MN+5],pn,np[MN+5],npn; 7 int main() 8 { 9 freopen("study.in","r",stdin); 10 freopen("study.out","w",stdout); 11 int n,i,j,x; 12 long long ans=0; 13 scanf("%d",&n); 14 for(i=1;i<=n;++i) 15 { 16 scanf("%d",&a[i]); 17 for(j=1;j<=pn;++j)a[p[j]]=gcd(a[p[j]],a[i]);p[++pn]=i; 18 for(j=1,npn=0;j<=pn;++j)if(j==pn||a[p[j]]!=a[p[j+1]])np[++npn]=p[j]; 19 for(j=1,pn=npn;j<=pn;++j)p[j]=np[j],ans=max(ans,1LL*a[p[j]]*(i-p[j-1])); 20 } 21 printf("%lld",ans); 22 fclose(stdin);fclose(stdout);return 0; 23 }
以上是关于10.25 AHSOFNU 校内模拟的主要内容,如果未能解决你的问题,请参考以下文章