10月10日考试复盘

T1:akinator


这题很简单,但是有三个方法:

1.二叉树法

将它的询问想象成一棵二叉树,'Y'就向左,'N'就向右,我们都知道二叉树的左子树为2*n,右子树为2*n+1,那我们定义一个变量x,遇到'Y',就*2,遇到'N',就*2+1,最后再减去[pow(2*n)-1]即可,因为得到的结论是叶子节点,且是按(1,2,3,4,5,6......)排的,所以要减去上面多算的那颗完美二叉树也就是[pow(2*n)-1]。

2.进制法

我们可以发现,如果我们将'Y'设为0,'N'设为1,则每一串问题我们都可以用一串二进制编码来表示,我们再将二进制编码,转十进制即可。

3.二分法

我们可以发现,它的询问是一棵二叉树的话('Y'设为0,'N'设为1)则得到一个回答,就可以排除一半的答案(选了右子树,排除左子树;选了左子树,排除右子树)。且我们要求的结论满足单调性,所以可以考虑二分。



T2:prim


这题还好(1秒的情况就不好了)

考验的是筛法,主要考察的是数学,筛法,快速幂(不会也可以手打pow),上一次我不知是为何是一个50分(10月4日)但这次对了,回到正题:

本题思路

一看题目标题,就看到了质数,我们就想到了埃氏筛(O(n log log n)),主要是不会欧拉筛(O(n)),本题给了2s够了不会超时。然后我们看题,发现答案只与质数和一有关,则我们将质数和1的个数分别用cnt和res存起来。我们又发现可以1和任何质数搭配且根据乘法原理(每个1都有两种选择:选或不选)那么公式就是pow(res)*cnt;

注意事项:

1.一定要取余(mod=1e9+7)。

2.一定要手打(pow函数);



T3:candy


这题分糖果(又是那种暴力简单,正解困难的题)

暴力就是枚举两个数然后将他们%m再取max;

正解(排序+二分):

1.我们可以提前先将它们与m取余 

2.我们取余之后,再排序

3.现在有了单调性,我们再枚举一个数,二分另一个数,使他们的和为不超过m的最大的数(若和>=m 往小的移动否则往大的移动)

4.ans在二分结束后取max

5.ans在最后要与(a[n]+a[n-1])%m(比m多的最大的数)取max

6.切记一定一定一定要初始化

代码放一下:

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+88;
long long n,T,a[N],m,ans=0;
bool vis[N];
void work(){
	ans=-1e9;
	cin >> n >> m;
	for(int i=1;i<=n;i++){
		cin >> a[i];
		a[i]%=m;
	}
	sort(a+1,a+n+1);
	for(int i=1;i<=n;i++){
//		cout<<"i="<<i<<endl;
		int l=i,r=n+1;
		while(l+1<r){
//			cout<<l<<' '<<r<<endl;
			int mid=(l+r)>>1;
			long long x=a[i]+a[mid];
//			cout<<x<<endl;
			if(x/m == 0){
				l=mid;
			}else{
				r=mid;
			}
		}
//		cout<<"l="<<l<<endl;
		if(l!=i) ans=max(ans,(a[i]+a[l])%m);
	}
	ans=max(ans,(a[n]+a[n-1])%m);
	cout << ans << endl;
}
int main(){
	freopen("candy.in","r",stdin);
	freopen("candy.out","w",stdout);
	cin >> T;
	while(T--){
		work();
	}
	return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值