Codeforces Round #677 (Div. 3) (A~E)

Codeforces Round #677 (Div. 3)

A.Boring Apartments

链接: A.Boring Apartments.
题意:一个调皮的小孩挨个给特殊编号的公寓楼打电话,直到打通为止,1~9999。
input
4
22
9999
1
777

output
13
90
1
66

代码

#include<iostream>
#include<cstring>

using namespace std;

int a[10050];

int main()
{
	int t;
	int y;
	for(int i=1; i<=9; i++)
	{
		int x = 0;
		for(int j=1; j<=4; j++)
		{
			x = x * 10 + i;
			a[x] = j;
		}	
	}	
	scanf("%d", &t);
	while(t--)
	{
		scanf("%d", &y);
		int ans = 0;
		int flag = 0;
		for(int i=1; i<=9; i++)
		{
			int x = 0;
			for(int j=1; j<=4; j++)
			{
				x = x * 10 + i;
				if(y != x)
				{
					ans += a[x];
				}
				else
				{
					ans += a[y];
					flag = 1;
					break;
				}	
			}
			if(flag)
			{
				break;
			}	
		}	
		printf("%d\n", ans);
	}
	return 0;
}

我这个是比较麻烦的做法,优化的话可以(n % 10 - 1) * 4 + n的位数。

B. Yet Another Bookshelf

题意:强迫症患者要把每本书之间的空隙给取消掉,问要挪动多少次,(以集合为单位进行挪动),一次只能移动一个位置
链接: B. Yet Another Bookshelf.
input
5
7
0 0 1 0 1 0 1
3
1 0 0
5
1 1 0 0 1
6
1 0 0 0 0 1
5
1 1 0 1 1

output
2
0
2
4
1

代码

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;

int a[100];

int main()
{
	int n;
	int t;
	scanf("%d", &t);
	while(t--)
	{
		int n, flag = 0, ans = 0, cnt = 0;
		
		scanf("%d", &n);
		for(int i=0; i<n; i++)
		{
			scanf("%d", &a[i]);
			if(a[i] == 1 && !flag)
			{
				flag = 1;
			}
			else if(flag && a[i] == 0)
			{
				cnt++;
			}
			else if(flag && a[i] == 1)
			{
				ans += cnt;
				cnt = 0;
			}
		}
		
		printf("%d\n", ans);
	}
	return 0;
} 

思路:其实就是计算0的个数(遇到第一个1之后的),可以看成是书从右往左进行挪动,每次挪到一起就变成了一个集合。

C.Dominant Piranha(大鱼吃小鱼)

链接: C Dominant Piranha.
题意:有一群食人鱼,在一个狭窄的水族箱里面,如果两只不同大小的食人鱼相邻,大鱼会吃小鱼,同时大鱼长大1个单位,问索引(位置)为多少的鱼可以成为最后的王者

input

6
5
5 3 4 4 5
3
1 1 1
5
4 4 3 4 4
5
5 5 4 3 2
3
1 1 2
5
5 4 3 5 5

output

3
-1
4
3
3
1

代码

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;

const int N = 3e5 + 10;

int a[N];

int main()
{
	int t;
	scanf("%d", &t);
	while(t--)
	{
		int n;
		int flag = 0;
		scanf("%d" ,&n);
		int maxn = 0; 
		for(int i=1; i<=n; i++)
		{
			scanf("%d", &a[i]);
			maxn = max(a[i], maxn);
		}
		int j = 1;
		a[0] = maxn;
		a[n+1] = maxn;
		for(int i=1; i<=n; i++)
		{
			if(a[i] == maxn && (a[i-1] < maxn || a[i+1] < maxn)) 
			{
				printf("%d\n", i);
				flag = 1;
				break;
			}
		}
		if(!flag)
		{
			printf("-1\n");
		}
	}
	return 0;
}

思路

找到最大的一条鱼,如果左右两边比他小,输出他的位置就可以了,注意最大的那条可能在开头,

D. Districts Connection

链接: D. Districts Connection.
题意:您是该市市长,希望修建n-1条双向道路,以连接所有地区(两个地区可以直接连接,也可以通过其他相连的地区连接)。但是市里面有黑帮,为了防止黑帮起义,不能在有相同黑帮的区之间修路,输出修路的方案。
input
4
5
1 2 2 1 3
3
1 1 1
4
1 1000 101 1000
4
1 2 3 4

output
YES
1 3
3 5
5 4
1 2
NO
YES
1 2
2 3
3 4
YES
1 2
1 3
1 4

代码

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 5555;

int a[N];
int vis[N];
int main()
{
	int n, t;
	scanf("%d", &t);
	while(t--)
	{
		scanf("%d", &n);
		int flag = 0;
		int j = 1;
		for(int i=1; i<=n; i++)
		{
			scanf("%d", &a[i]);
			if(a[1] == a[i] && i != 1)
			{
				vis[j++] = i;
			}
		}
		if(j != n)
		{
			puts("YES");
			for(int i=1; i<=n; i++)
			{
				if(a[1] != a[i])
				{
					flag = i;
					printf("1 %d\n", i);
				}
			}		
			for(int k=1; k<j; k++)
			{
				printf("%d %d\n", flag, vis[k]);
			}
		}
		else
		{
			puts("NO");	
		}			
	}
	return 0;
}

思路

找到两个不同黑帮的区,以这两个区为中心修路即可

E. Two Round Dances

链接: E. Two Round Dances.
题意:问两种组合的舞蹈可以有多少不同组合的人参与
input
2
4
8
20

output
1
3
1260
12164510040883200

代码

#include<iostream>

using namespace std;

typedef unsigned long long ull;

ull A(int x, int y)
{
	ull ans = 1;
	for(int i=0; i<y; i++)
	{
		ans *= x--;
	}
	return ans;
}
ull C(int x, int y)
{
	ull ans = 1;
	for(int i=0; i<y; i++)
	{
		ans *= x--;
	}
	ans /= A(y, y);
	return ans;
}
int main()
{
	int n;
	scanf("%d", &n);
	ull ans = C(n, n/2) * A(n/2, n/2) * A(n/2, n/2) / (n/2) / (n/2) / 2;
	cout << ans;
	return 0; 
}
思路:

其实就是排列组合问题,先挑选n/2个人,对n/2个人进行排列,因为是圆排列,所以还要除以n/2,最后除以2去重

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值