洛谷p10892题解

发布于:2024-08-22 ⋅ 阅读:(49) ⋅ 点赞:(0)

题目背景

AzureHair 在 NOIP 2022 中被喵了个喵创死,于是患上了不治之症——T2 恐惧症,于是他在 NOIP 2023 中果断跳过了 T2 并杠 T3 两小时无果,遗憾离场,他的同学决定帮他治疗这种不治之症。

在他的同学给他治愈了 T2 恐惧症后,他自信的开始了他的 SDOI,遂分讨写了 22 个小时没写出来,遗憾离场……

题目描述

AzureHair 的同学把 AzureHair 和 n 只猫猫关在一个房间里,并且要求 AzureHair 每过一天就交出 n/2​ 只猫猫,但是如果 n 是奇数时,AzureHair 就会纠结于要交出 (n+1)/2​ 只猫猫还是交出 (n−1)/2​ 只猫猫。AzureHair 不想让自己纠结,所以请你计算出直到所有猫猫都被拿出房间时,AzureHair 的最小纠结次数是多少。

输入格式

本题有多组测试数据。

第一行一个整数 T。

接下来 T 行,每行一个整数 n。

输出格式

T 行,每行一个整数表示最小纠结次数。

输入输出样例

输入 #1复制

2
13
7

输出 #1复制

3
2

说明/提示

【样例解释】

对于 13 只猫猫,只纠结 3 次的过程如下:

选择交出 7 只猫猫,剩余 6 只;

不纠结,交出 3 只猫猫,剩余 3 只;

选择交出 2 只猫猫,剩余 1 只;

选择交出 1 只猫猫,所有猫猫均被取走。

容易证明不存在少于 3 次纠结的方案。

【数据范围】

对于 10% 的数据,保证 1≤n≤10。

对于 30% 的数据,保证 1≤n≤10^5。

对于 100% 的数据,保证 1≤n≤2^60,1≤T≤5×10^5。

思路:

考虑dfs搜索。

#include<bits/stdc++.h>
using namespace std;
int n,s,ans;
void dfs(int num,int step){
	if(num==0){
		ans=min(step,ans);
		return;
	}
	else if(num==1){
		ans=min(step+1,ans);
		return;
	}
	else if(num%2==0)dfs(num/2,step);
	else{
		dfs((num+1)/2,step+1);
		dfs((num-1)/2,step+1);
	}
}
int main(){
	cin>>n;
	while(n--){
		ans=10000;
		cin>>s;
		dfs(s,0);
		cout<<ans<<"\n";
	}
}

结果30pts,其他都TLE了。

考虑动态规划。

#include<bits/stdc++.h>
using namespace std;
const int mod=1000;
long long n,s,ans,f[mod];
int main(){
	cin>>n;
	while(n--){
		cin>>s;
		f[0]=0;
		f[1]=1;
		for(int j=2;j<=s;j++){
			if(j%2==0)f[j%mod]=f[j/2%mod];
			else f[j%mod]=min(f[(j+1)/2%mod],f[(j-1)/2%mod])+1;
		}
		cout<<f[s%mod]<<"\n";
	}
}

还是TLE了

考虑正解。

正解:

如果是奇数,纠结次数+1,

还如果减一除以二为奇数,则n+1

n/=2

Code:

#include<bits/stdc++.h>
using namespace std;
long long t,n,ans;
int main(){
	cin>>t;
	while(t--){
		cin>>n;
		ans=0;
		while(n){
			if(n&1){
				ans++;
				if(n&2)n++;
			}
			n>>=1;
		}
		cout<<ans<<"\n";
	}
}