Codeforces Round #302 (Div. 2) (ABCD题解)

54 篇文章 0 订阅
53 篇文章 0 订阅

比赛链接:http://codeforces.com/contest/544


A. Set of Strings
time limit per test:1 second
memory limit per test:256 megabytes

You are given a string q. A sequence of k strings s1, s2, ..., sk is called beautiful, if the concatenation of these strings is string q (formally, s1 + s2 + ... + sk = q) and the first characters of these strings are distinct.

Find any beautiful sequence of strings or determine that the beautiful sequence doesn't exist.

Input

The first line contains a positive integer k (1 ≤ k ≤ 26) — the number of strings that should be in a beautiful sequence.

The second line contains string q, consisting of lowercase Latin letters. The length of the string is within range from 1 to 100, inclusive.

Output

If such sequence doesn't exist, then print in a single line "NO" (without the quotes). Otherwise, print in the first line "YES" (without the quotes) and in the next k lines print the beautiful sequence of strings s1, s2, ..., sk.

If there are multiple possible answers, print any of them.

Sample test(s)
Input
1
abca
Output
YES
abca
Input
2
aaacas
Output
YES
aaa
cas
Input
4
abc
Output
NO
Note

In the second sample there are two possible answers: {"aaaca", "s"} and {"aaa", "cas"}.

题目大意:把一个给定的母串分成k个子串,要求k个子串的和为母串,且k个子串的首字符不能相同

题目分析:标记一下首字符出现的情况再统计一下分成的份数即可


#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
using namespace std;

int main()
{
	int k;
	cin >> k;
	string s;
	cin >> s;
	string ans[30];
	int cnt = 1;
	int len = s.length();
	bool hash[400];
	memset(hash, false, sizeof(hash));
	bool flag = false;
	for(int i = 0; i < len; i++)
	{
		if(!hash[s[i]])
		{
			hash[s[i]] = true;
			ans[cnt ++] += s[i];
		}
		else if(hash[s[i]] || s[i] == s[i - 1])
			ans[cnt - 1] += s[i];
		if(cnt == k + 1)
		{
			for(int j = i + 1; j < len; j++)
				ans[cnt - 1] += s[j];
			flag = true;
			break;
		}
	}
	if(!flag)
		printf("NO\n");
	else
	{
		printf("YES\n");
		for(int i = 1; i < cnt; i++)
			cout << ans[i] << endl;
	}
}



B. Sea and Islands
time limit per test:1 second
memory limit per test:256 megabytes

A map of some object is a rectangular field consisting of n rows and n columns. Each cell is initially occupied by the sea but you can cover some some cells of the map with sand so that exactly k islands appear on the map. We will call a set of sand cells to be island if it is possible to get from each of them to each of them by moving only through sand cells and by moving from a cell only to a side-adjacent cell. The cells are called to be side-adjacent if they share a vertical or horizontal side. It is easy to see that islands do not share cells (otherwise they together form a bigger island).

Find a way to cover some cells with sand so that exactly k islands appear on the n × n map, or determine that no such way exists.

Input

The single line contains two positive integers n, k (1 ≤ n ≤ 100, 0 ≤ k ≤ n2) — the size of the map and the number of islands you should form.

Output

If the answer doesn't exist, print "NO" (without the quotes) in a single line.

Otherwise, print "YES" in the first line. In the next n lines print the description of the map. Each of the lines of the description must consist only of characters 'S' and 'L', where 'S' is a cell that is occupied by the sea and 'L' is the cell covered with sand. The length of each line of the description must equal n.

If there are multiple answers, you may print any of them.

You should not maximize the sizes of islands.

Sample test(s)
Input
5 2
Output
YES
SSSSS
LLLLL
SSSSS
LLLLL
SSSSS
Input
5 25
Output
NO

题目大意:把一个区域分成k个岛输出方案,岛就是一个四个方向的连通块

题目分析:隔一格,填一个岛,填到k个为止,注意最多可能出现的岛的个数为(n * n + 1) / 2


#include <cstdio>

int main() 
{
	int n, k;
	scanf("%d %d", &n, &k);
	if((n * n + 1) / 2 < k)
		printf("NO\n");
	else
	{
		printf("YES\n");
		for(int i = 1; i <= n; i++)
		{
			for(int j = 1; j <= n; j++)
			{ 
				if((i + j) % 2 == 0 && k > 0) 
				{
					printf("L");
					k --;
				}
				else 
					printf("S");
			}
			printf("\n");
		}
	}
}



C. Writing Code
time limit per test:3 seconds
memory limit per test:256 megabytes

Programmers working on a large project have just received a task to write exactly m lines of code. There are n programmers working on a project, the i-th of them makes exactly ai bugs in every line of code that he writes.

Let's call a sequence of non-negative integers v1, v2, ..., vn a plan, if v1 + v2 + ... + vn = m. The programmers follow the plan like that: in the beginning the first programmer writes the first v1 lines of the given task, then the second programmer writes v2 more lines of the given task, and so on. In the end, the last programmer writes the remaining lines of the code. Let's call a plan good, if all the written lines of the task contain at most b bugs in total.

Your task is to determine how many distinct good plans are there. As the number of plans can be large, print the remainder of this number modulo given positive integer mod.

Input

The first line contains four integers n, m, b, mod (1 ≤ n, m ≤ 500, 0 ≤ b ≤ 500; 1 ≤ mod ≤ 109 + 7) — the number of programmers, the number of lines of code in the task, the maximum total number of bugs respectively and the modulo you should use when printing the answer.

The next line contains n space-separated integers a1, a2, ..., an (0 ≤ ai ≤ 500) — the number of bugs per line for each programmer.

Output

Print a single integer — the answer to the problem modulo mod.

Sample test(s)
Input
3 3 3 100
1 1 1
Output
10
Input
3 6 5 1000000007
1 2 3
Output
0
Input
3 5 6 11
1 2 1
Output
0


题目大意:n个人,一共要写m行程序,每个程序员每行出现的bug数为ai,要求整个程序出现的bug数不超过b的方案数

题目分析:看出来是多重背包就没什么了,dp[i][j]表示前i行出现j个bug的方案数,然后就是背包计数问题


#include <cstdio>
#include <cstring>
int const MAX = 505;
int a[MAX], dp[MAX][MAX];

int main()
{
    int n, m, b, MOD;
    scanf("%d %d %d %d", &n, &m, &b, &MOD);
    for(int i = 1; i <= n; i++) 
    	scanf("%d", &a[i]);   
    dp[0][0] = 1;
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
            for(int k = a[i]; k <= b; k++) 
            	dp[j][k] = (dp[j][k] + dp[j - 1][k - a[i]]) % MOD;
    int ans = 0;
    for(int i = 0; i <= b; i++) 
    	ans = (ans + dp[m][i]) % MOD;
    printf("%d\n", ans);
}



D. Destroying Roads
time limit per test:2 seconds
memory limit per test:256 megabytes

In some country there are exactly n cities and m bidirectional roads connecting the cities. Cities are numbered with integers from 1 to n. If cities a and b are connected by a road, then in an hour you can go along this road either from city a to city b, or from city b to city a. The road network is such that from any city you can get to any other one by moving along the roads.

You want to destroy the largest possible number of roads in the country so that the remaining roads would allow you to get from city s1 to city t1 in at most l1 hours and get from city s2 to city t2 in at most l2 hours.

Determine what maximum number of roads you need to destroy in order to meet the condition of your plan. If it is impossible to reach the desired result, print -1.

Input

The first line contains two integers n, m (1 ≤ n ≤ 3000, ) — the number of cities and roads in the country, respectively.

Next m lines contain the descriptions of the roads as pairs of integers ai, bi (1 ≤ ai, bi ≤ n, ai ≠ bi). It is guaranteed that the roads that are given in the description can transport you from any city to any other one. It is guaranteed that each pair of cities has at most one road between them.

The last two lines contains three integers each, s1, t1, l1 and s2, t2, l2, respectively (1 ≤ si, ti ≤ n, 0 ≤ li ≤ n).

Output

Print a single number — the answer to the problem. If the it is impossible to meet the conditions, print -1.

Sample test(s)
Input
5 4
1 2
2 3
3 4
4 5
1 3 2
3 5 2
Output
0
Input
5 4
1 2
2 3
3 4
4 5
1 3 2
2 4 2
Output
1
Input
5 4
1 2
2 3
3 4
4 5
1 3 2
3 5 1
Output
-1

题目大意:无向图n个点,m条边,要求去掉最多的边使得从s1到t1的时间不超过l1且从s2到t2的时间不超过l2

题目分析:考虑到n的范围又边权固定为1,用bfs求出任意两点间的最短路,然后就是枚举s1到t1和s2到t2路径上的边了(其他不与其相关的边肯定直接被删掉),取最小值即可


#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
int const MAX = 3005;
vector <int> vt[MAX];
int dis[MAX][MAX];
bool vis[MAX];
int n, m;

void BFS()
{
	memset(dis, 0, sizeof(dis));
	for(int i = 1; i <= n; i++)
	{
		memset(vis, false, sizeof(vis));
		queue <int> q;
		vis[i] = true;
		q.push(i);
		while(!q.empty())
		{
			int u = q.front();
			q.pop();
			int sz = vt[u].size();
			for(int j = 0; j < sz; j++)
			{
				int v = vt[u][j];
				if(!vis[v])
				{
					vis[v] = true;
					dis[i][v] = dis[i][u] + 1;
					q.push(v);
				}
			}
		}
	}
}

int main()
{
	scanf("%d %d", &n, &m);
	for(int i = 0; i < m; i++)
	{
		int x, y;
		scanf("%d %d", &x, &y);
		vt[x].push_back(y);
		vt[y].push_back(x);
	}
	int s1, t1, l1, s2, t2, l2;
	scanf("%d %d %d %d %d %d", &s1, &t1, &l1, &s2, &t2, &l2);
	BFS();
	if(!(dis[s1][t1] <= l1 && dis[s2][t2] <= l2))
	{
		printf("-1\n");
		return 0;
	}
	int tmp = dis[s1][t1] + dis[s2][t2];
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= n; j++)
		{
			if(dis[s1][i] + dis[i][j] + dis[j][t1] <= l1 && dis[s2][i] + dis[i][j] + dis[j][t2] <= l2)
				tmp = min(tmp, dis[s1][i] + dis[i][j] + dis[j][t1] + dis[s2][i] + dis[j][t2]);
			if(dis[s1][i] + dis[i][j] + dis[j][t1] <= l1 && dis[t2][i] + dis[i][j] + dis[i][s2] <= l2)
				tmp = min(tmp, dis[s1][i] + dis[i][j] + dis[j][t1] + dis[t2][i] + dis[i][s2]);
			if(dis[t1][i] + dis[i][j] + dis[j][s1] <= l1 && dis[s2][i] + dis[i][j] + dis[j][t2] <= l2)
				tmp = min(tmp, dis[t1][i] + dis[i][j] + dis[j][s1] + dis[s2][i] + dis[j][t2]);
			if(dis[t1][i] + dis[i][j] + dis[j][s1] <= l1 && dis[t2][i] + dis[i][j] + dis[j][s2] <= l2)
				tmp = min(tmp, dis[t1][i] + dis[i][j] + dis[j][s1] + dis[t2][i] + dis[j][s2]);
		}
	printf("%d\n", m - tmp);
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值