高一部阶段考试 题解

高一部阶段考试 题解

数的变化(dis.cpp)

题目:

【问题描述】

给出两个整数a和h,每次操作可以a+1或a×2,问至少进行多少次操作可以使得a=b。

【输入格式】

一行两个整数a和b,之间有一个空格。

【输出格式】

一行一个整数ans,表示至少进行多少次操作可以使得a=b。

【输入样例】

2 10

【输出样例】

3

【数据规模】

对于30%的数据满足:1≤a≤b≤100

对于60%的数据满足:1≤a≤h≤10^6

对于l00%的数据满足:1≤a≤b≤10^9

题解:

考虑贪心,显然a*2操作对答案的贡献比a+1操作的贡献大;但是显然仅仅乘以2并不一定能得到目标值(b)

先尝试正向求出几组小数据:

数据1:

2 10

存在

2*2 = 4;

4 + 1 = 5;

5*2 = 10;

数据2:

3 11

3+1 = 4;

4+1 = 5;

5*2 = 10;

10+1 = 11;

可以看出一些规律,但是计算机如果正向算的话就是搜索了,时间复杂度太大,可以考虑逆向算

读入 a,b;

判断b是否等于a 是则**结束计数****

如果 b为奇数b = b-1

如果b为偶数

​ 若b/2 >= a 则令 b = b/2;res++

​ 否则 令 res += (b-a);结束计数

时间复杂度O(logb)

#include <cstdio>
#include <algorithm>
#include <iostream>
using namespace std;
int a,b;
int main(void)
{
	int res = 0;
	cin >>a>>b;
	while(b != a)
	{
		res++;
		if(b % 2 == 0 && b/2 >= a) b /= 2;
		else b = b-1;
		if(b-1 == a)
		{
			res++;
			break;
		} 
	}
	cout << res;
	return 0;
}

分身数对(sumx.cpp)

题目:

【问题描述】

给出n个不同的正整数a[1]~a[n],它们的值在1~1000000之间。再给定一个整数x,编程计算这样的数对个数(a [i],a[j]),l≤i<j≤n并且a[i]+a[j ]=x。

【输入格式】

第1行1个正整数n,1≤n≤100000。

第2行n个正整数,表示元素a[1]~a[n],每两个数之间用一个空格分隔。

第3行1个正整数x,1≤x≤2000000。

【输出格式】

一行一个整数,表示这样的数对个数。

【输入样例】

9

5 12 7 10 9 1 2 3 11

13

【输出样例】

3

【样例说明】

不同的和为13的数对是(12,1),(10,3)和(2,11),共3对。

#include <algorithm>
#include <cstdio>
using namespace std;
//常量声明
#define N 1000001
//类型声明
//变量声明
bool num[N];

//函数声明 
int main(void)
{
	//freopen("1.in","r",stdin);
	//named
	int n,a;
	int res = 0;
	int x,x_i;
	//read
	scanf("%d",&n);
	for(register int i = 1 ; i <= n ; i++) 
	{
		scanf("%d",&a);
		num[a] = true;
	}
	scanf("%d",&x);
	//doing
	x_i = x/2;
	if(x % 2 == 0) x_i--;
	for(int i = 1 ; i <= x_i ; i++)
	{
		if(num[i] && num[x-i])res++;
	}
	printf("%d",res);
	return 0;
}

题解:

建个布尔随便扫扫了,时间复杂度O(n)

P.S. 注意如果为偶数则枚举上限-1

最大的子序列和(maxsum.cpp)

题目

【问题描述】

给出一串整数a[1],a[2],a[3],…,a[n],求出它最大的子序列和,即找出1≤i≤j≤n,使a[i]+ a[i+1]+…+a[j]最大。

【输入格式】

第1行1个整数n,表示整数序列的个数。

第2行有n个整数[-32768,32767],表示a[i],1≤i≤n。

【输出格式】

输出一行一个数,表示最大的子序列和。

【输入样例】

10

3 1 -6 1 7 5 -2 5 -100 10

【输出样例】

16

【数据规模】

对于30%的数据满足:n≤10^2。

对于50%的数据满足:n≤10^4。

对于80%的数据满足:n≤10^6。

对于l00%的数据满足:n≤10^7。

题解:

裸DP;

设状态F[i]为以i为结尾的子序列的最大和

状态及阶段

则转移方程为:F[i] = max(a,F[i-1]+a);

P.S.

可以边读入边计算并加以滚动数组优化

一定要用快读

#include <cstdio>
#include <algorithm>
using namespace std;
//常量声明
#define N (int)1e7+1
//类型声明
//变量声明 
int f[2];
int max_sum = -0x7fffffff; 
//函数声明 
inline void read(int &v)
{
    register int num;char a;bool flag=0;
    while((a=getchar())<48||a>57)flag^=!(a^'-');
    num=a^48;
    while((a=getchar())>=48&&a<=57)num=(num<<3)+(num<<1)+(a^48);
    v=flag? -num:num;
    return;
}
int main(void)
{
	//named
	int n;
	int a;
	//read&&dp
	read(n);
	for(int i = 1 ; i <= n ; i++)
	{
		read(a);
		f[i&1] = max(f[(i-1)&1]+a,a);
		max_sum = max(f[i&1],max_sum);
	}
	printf("%d",max_sum);
	return 0;
}

相遇问题(meeting.cpp)

题目:

【问题描述】

​ 贝丽斯和她的姐姐艾丽斯想从谷仓走到她们最喜爱的牧场。她们在同一时间离开谷仓,也在同一时间到达最喜爱的牧场。

​ 整个农场是一个有N个牧场,1号牧场就是谷仓,N号牧场是她们最喜爱的牧场。整个农场是建在一个山坡上的,如果X<Y,则代表x号牧场比Y牧场要高。有M条路径连接一堆牧场。然而,由于每条路径都很陡,每条路只能向下山的方向走。比如,一条连接5号和8号农场的路只能从5走到8而不能反过来,因为那样就是向山上走了。每对牧场之间最多有一条路径,故M≤N(N-1)/2。

​ 贝丽斯和艾丽斯可能需要不同的时间米走过一条路径。例如,贝丽斯可能花l0个单位的时间,而艾丽斯会花20个单位,而且她们只在路径上花时间,在牧场上是不花时间的。

​ 请帮助决定贝丽斯和艾丽斯至少要花多少时间,使她们能同时到达她们最喜爱的农场。

【输入格式】

第1行是N和M,用一个空格分开。

​ 接下来的M行,每行有4个整数A、B、C、D,表示A牧场和B牧场是被连接的,C是贝丽斯经过这条路要花的时间,D是艾丽斯经过这条路要花的时间。C和D的范围是1~1000。

【输出格式】

​ 一行一个整数,表示贝丽斯和艾丽斯至少要花多少时间使她们能同时到达她们最喜爱的农场。如果这是不可能的,或者根本就没有路径使她们能到达她们最喜爱的农场,在一行输出“IMPOSSIBLE”。

【输入样例】

3 3

1 3 1 2

1 2 1 2

2 3 1 2

【输出样例】

2

【样例解释】

贝丽斯在每条路径上都比艾丽斯走得速度快1倍;但是如果贝丽斯采用路径1→2→3,艾丽斯采用路径l→3,那么她们将在同一时间到达。

【数据范围】

对于20%的数据满足:N≤5。

对于60%的数据满足:M≤90。

对于l00%的数据满足:1≤N≤16,M≤N(N-1)/2。

题解

暴力搜索两个人可能的路径和情况,然后进行对比,找出最小且公共的

P.S.

存路径和情况的数组一定要开的足够大

#include <cstdio>
#include <algorithm>
using namespace std;
//常量声明 
#define N 17
#define D 100000
//类型声明
//变量声明
int road[N][N][2];	//0 elder 1 little 
int sum_r[2][D];
int cnt[2];
int n,m;
//函数声明 
void dfs(int k,int u,int t,int sum);
int main(void)
{
	//named
	int a,b,c,d;
	//read
	scanf("%d%d",&n,&m);
	for(int i = 1 ; i <= m ; i++) 
	{
		scanf("%d%d%d%d",&a,&b,&c,&d);
		road[a][b][0] = road[b][a][0] = c;	
		road[a][b][1] = road[b][a][1] = d;
	}
	//dfs
	dfs(0,1,n,0);
	dfs(1,1,n,0);
	//sort
	sort(sum_r[0],sum_r[0]+cnt[0]);	
	sort(sum_r[1],sum_r[1]+cnt[1]);	
	for(int i = 0 ; i < cnt[0] ; i++)
		for(int j = 0 ; j < cnt[1] && sum_r[1][j] <= sum_r[0][i] ; j++)
			if(sum_r[0][i] == sum_r[1][j])
			{
				printf("%d",sum_r[0][i]);
				return 0;
			}
	puts("IMPOSSIBLE");
	return 0;
}
void dfs(int k,int u,int t,int sum)
{
	if(u == t) 
	{
		sum_r[k][cnt[k]++] = sum;
	}
	for(register int i = u+1 ; i <= n ; i++) 
		if(road[u][i][k]) dfs(k,i,t,sum+road[u][i][k]);
	return;
}
posted @ 2019-04-16 21:34  白萝卜_胡萝卜  阅读(657)  评论(0编辑  收藏  举报
……