【2020.10.29普及组】SSL模拟赛题解

目录:

T1:捡石头
T2:魔法药水
T3:土地恢复
T4:组合数
T5:排数字
T6:小武的方程

T1:捡石头

题目描述

地上有2N个石头,排成了一条线,相邻的石头距离为1,石头之间有着不同的大小,有N种大小不同 的石头,即相同大小的石头有2个,现将石头按照从小到大的顺序依次编号为1到N,有2个石头共享 相同的编号,现在小武和小林要同时从最左边的石头出发,按照石头大小依次捡起编号为1到N的石 头,并且相同编号的石头同一个人只能捡起来一次,现在他们想把地上的石头都捡完,求两个人的行 走的最短距离和为多少?

输入格式

第一行一个正整数N 第二行2N个数,按照石头从左到右的顺序依次给出石头的编号

输出格式

一行一个数表示行走的最短距离和

输入输出样例

输入 #1

3
1 1 2 2 3 3

输出 #1

9

输入 #2

4
2 2 3 4 4 1 1 3

输出 #2

33

输入 #3

3
1 3 1 2 3 2

输出 #3

11

分析:

可以用 d p dp dp做 也可以直接模拟

CODE:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int n,ans;
struct node{
    
    
	int x,y;
}a[101000];
bool cmp(node l,node r)
{
    
    
	if(l.x==r.x)return l.y<r.y;
	return l.x<r.x;
}
int main(){
    
    
	scanf("%d",&n);
	for(int i=1;i<=2*n;i++)
	{
    
    
		scanf("%d",&a[i].x);
		a[i].y=i;
	}
	sort(a+1,a+n*2+1,cmp);
	ans=a[1].y-1+a[2].y-1;
	for(int i=3;i<=n*2;i++)
		ans=ans+abs(a[i].y-a[i-2].y);
	printf("%d",ans);
}

T2:魔法药水

题目描述

小武的实验室里有一种魔法药水,这个药水有个很奇怪的性质,它只能在盛放的体积为2的幂次时保 持稳定,例如1,2,4,8。所以小武在实验室里放置了很多容积为2的幂次的瓶子,其中N瓶放有魔法药 水,第i瓶魔法药水的体积为2的L[i]次方。这天小武想要收拾一下实验室,小武想知道最少用多少个瓶 子能把实验室的药水装完。
假设小武有任意2的幂次容积的瓶子,并且每种瓶子的数量足够使用。

输入格式

第一行一个正整数N
第二行N个数,表示L[i]

输出格式

一行一个数表示最少需要多少个瓶子

输入输出样例

输入 #1

5
1 1 2 3 3

输出 #1

2

输入 #2

6
7 6 4 6 7 0

输出 #2

4

输入 #3

7
8 6 6 8 2 8 4

输出 #3

5

分析:

记录当前的值 每两个可以组成一个更大的

CODE:

#include<cstdio>
#include<iostream>
#define ll long long
using namespace std;
int n,a[10000005],maxi;
ll ans;
int main()
{
    
    
	scanf("%d",&n);
	for(register int i=1;i<=n;i++)
	{
    
    
		int x;
		scanf("%d",&x);
		a[x]++;
		maxi=max(maxi,x);
	}
	for(register int i=0;i<=maxi;i++)
	{
    
    
		if(a[i]>1)
		{
    
    
			a[i+1]+=a[i]/2;  
			a[i]%=2;
			if(i==maxi) maxi++;
		}
	}
	for(register int i=0;i<=maxi;i++)
		if(a[i]) ans++;
	printf ("%lld",ans);
	return 0;
}

T3:土地恢复

题目描述

宣文胜的家乡山西省是我国的产煤大省,因为长期挖煤导致了他家乡的某些地方出现了地陷的情况。 近几年国家大力开展环境整治和土地复耕,让人民不仅享受经济发展所带来的红利更要还老百姓绿水 青山。为了把这些地陷的土地恢复平整,他的家乡决定聘请他负责这项工作。

他负责恢复的是一条长度为n的土地,恢复土地的主要工作是填平下陷的地表。需要恢复的土地可以 看作是n块首尾相连的区域,一开始,第i块区域下陷的深度为di。宣文胜决定每天选择一段连续区间 [M, N] ,填充这段区间中的每块区域,让其下陷深度减少1。在选择区间时,需要保证,区间内的每 块区域在恢复前下陷深度均不为0 。

宣文胜希望你能帮他设计一种方案,可以在最短的时间内将整块土地的下陷深度都变为0。

输入格式

第一行输入一个整数n,表示恢复土地的长度。
第二行n个整数di,以空格隔开。

输出格式

输出一个整数,即最少需要多少天才能完成任务。

输入输出样例

输入 #1

6
4 3 2 5 3 5

输出 #1

9

输入 #2

4
2 5 3 5

输出 #2

7

输入 #3

12
2 6 5 8 9 12 15 7 5 10 16 24

输出 #3

35

分析:

一个贪心 相邻的两个坑互相填 则小坑会被大坑带掉
大坑就减少了 a [ i ] − a [ i − 1 ] a[i]-a[i-1] a[i]a[i1]的高度

CODE:

#include<cstdio>
#include<iostream>
#include<algorithm> 
using namespace std;
int n,sum,l;
int main()
{
    
    
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
    
    
        int x;
        scanf("%d",&x);
        if(x>l)
		sum+=(x-l);
        l=x;
    }
    printf("%d",sum);
    return 0;
}

T4:组合数

题目描述

输入格式

第一行有两个整数t,k,其中t表示该测试点总共有多少组测试数据,k的意义见「题目描述」。
接下来t行每行两个整数n,m,其中n,m的意义见「题目描述」。

输出格式

输出共t行,每行一个整数代表对于所有的 0 ≤ i ≤ n, 0 ≤ j ≤ min(i,m) 有多少对 (i, j) 满足 C(i,j)是k 的倍数。

输入输出样例

输入 #1

1 2
3 3

输出 #1

1

输入 #2

2 5
4 5
6 7

输出 #2

0
7

输入 #3

3 6
2 8
4 6
6 9

输出 #3

0
1
3

分析:

暴力枚举肯定是不行的 正解为预处理杨辉三角
然后做二维前缀和 每次 m o d mod mod k k k

CODE:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
ll t,num[2002][2002];
int k,f[2002][2002];
void tri(){
    
    
	f[0][0]=f[1][0]=f[1][1]=1;
	for(int i=2;i<=2000;i++)
	{
    
    
		f[i][0]=1;
		for(int j=1;j<=i;j++)
		{
    
    
			f[i][j]=(f[i-1][j-1]%k+f[i-1][j]%k)%k;  //杨辉三角
			num[i][j]=num[i-1][j]+num[i][j-1]-num[i-1][j-1];  //前缀和
			if(f[i][j]==0) num[i][j]++;
		}
		num[i][i+1]=num[i][i];
	}
}
int main (){
    
    
	scanf("%lld%d",&t,&k);
	tri();
	while(t--)
	{
    
    
		int m,n;
		scanf("%d%d",&n,&m);
		if(m>n) printf("%lld\n",num[n][n]);
		else printf("%lld\n",num[n][m]);
	}
	return 0;
}

T5:排数字

题目描述

小武有n个数字,这天小武想将数字理的顺一点,小武要把数字分组,每组的个数都是m,并且这m个 数字连续,小武想知道可以做到吗?

输入格式

第一行一个整数t表示数据组数 对于每组数据, 第一行两个整数n,m 第二行N个非负整数,表示数字

输出格式

如果可以做到输出 “ t r u e ” “true” true,否则输出 “ f a l s e ” “false” false

输入输出样例

输入 #1

3
9 3
1 2 3 6 2 3 4 7 8
6 3
1 2 3 4 6 7
6 3
1 2 3 4 5 6

输出 #1

true
false
true

分析:

模拟 每一个没选的数 判断如果以他开头能不能排出
如果不能直接 f a l s e false false 否则 t r u e true true

CODE:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m,a[100105];
bool f[10005];
int main()
{
    
    
	int t;
	scanf("%d",&t);
	while(t--)
	{
    
    
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++)
			scanf("%d",&a[i]);
		sort(a+1,a+1+n);
		if(n%m!=0){
    
    printf("false\n");continue;}  //无法凑m组
		int be=0,u=1;
		for(int i=1;i<=n/m;i++)
		{
    
    
			if(u==0) break;
			int j=be+1,k=a[j];
			f[j]=1;
			int qwq=1,T=0;
			while(j<n&&qwq<m)
			{
    
    
				j++;
				if(f[j]==1)
					if(a[j]-k>1){
    
    u=0;break;}
				else
				{
    
    
					if(a[j]-k>1){
    
    u=0;break;}
					else
					if(a[j]-k==1){
    
    f[j]=1;qwq++;k=a[j];}  //不断匹配
					else
					if(a[j]==k&&T==0){
    
    T=1;be=j-1;}  
				}
			}
			if(T==0) be=j; 
			if(qwq!=m){
    
    u=0;break;}  //无法匹配m个
			
		}
		if(u==0) printf("false\n");
		else printf("true\n");
		memset(f,0,sizeof(f));
	}
	return 0;
}

T6:小武的方程

题目描述

小武有2个方程,x|y=A,x+y=B,其中|为二进制或符号,x和y是未知数,A和B已知,小武想知道这个 方程是否有非负整数解。

输入格式

第一行一个整数T表示数据组数
接下来T行,每行两个数A和B

输出格式

T行,若方程有解输出 P o s s i b l e Possible Possible,否则输出 I m p o s s i b l e Impossible Impossible

输入输出样例

输入 #1

4
14 14
2 5
0 9
10 10

输出 #1

Possible
Impossible
Impossible
Possible

分析:

x x x设为 A A A y = B − A ( x + y = B ) y=B-A(x+y=B) y=BA(x+y=B)
这样再把( A A A B − A B-A BA异或一下) 判断等不等于 A A A即可
这样就不用 O ( T ∗ n 2 ) O(T*n^2) O(Tn2) 去枚举 直接 O ( T ) O(T) O(T)

CODE:

#include<iostream>
#include<cstdio>
using namespace std;
int t;
int main()
{
    
    
 	scanf("%d",&t);
 	while(t--)
 	{
    
    
 		long long a,b;
 		scanf("%lld%lld",&a,&b);
 		long long ans=a|(b-a);
 		if((b>=a)&&ans==a)
 			printf("Possible\n");
 		else 
 			printf("Impossible\n");
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/dgssl_xhy/article/details/109371605
今日推荐