codeforces-486【C-贪心-思维】【D-树状DP】

52 篇文章 0 订阅
27 篇文章 0 订阅

题目链接:点击打开链接

A. Calculating Function
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

For a positive integer n let's define a function f:

f(n) =  - 1 + 2 - 3 + .. + ( - 1)nn

Your task is to calculate f(n) for a given integer n.

Input

The single line contains the positive integer n (1 ≤ n ≤ 1015).

Output

Print f(n) in a single line.

Examples
input
4
output
2
input
5
output
-3
Note

f(4) =  - 1 + 2 - 3 + 4 = 2

f(5) =  - 1 + 2 - 3 + 4 - 5 =  - 3


#include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long
using namespace std;
LL n;
int main()
{
	while(~scanf("%I64d",&n))
	{
		printf("%I64d\n",(n&1?n/2-n:n/2));
	}
	return 0;
}

题目链接: 点击打开链接

B. OR in Matrix
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Let's define logical OR as an operation on two logical values (i. e. values that belong to the set {0, 1}) that is equal to 1 if either or both of the logical values is set to 1, otherwise it is 0. We can define logical OR of three or more logical values in the same manner:

 where  is equal to 1 if some ai = 1, otherwise it is equal to 0.

Nam has a matrix A consisting of m rows and n columns. The rows are numbered from 1 to m, columns are numbered from 1 to n. Element at row i (1 ≤ i ≤ m) and column j (1 ≤ j ≤ n) is denoted as Aij. All elements of A are either 0 or 1. From matrix A, Nam creates another matrix B of the same size using formula:

.

(Bij is OR of all elements in row i and column j of matrix A)

Nam gives you matrix B and challenges you to guess matrix A. Although Nam is smart, he could probably make a mistake while calculating matrix B, since size of A can be large.

Input

The first line contains two integer m and n (1 ≤ m, n ≤ 100), number of rows and number of columns of matrices respectively.

The next m lines each contain n integers separated by spaces describing rows of matrix B (each element of B is either 0 or 1).

Output

In the first line, print "NO" if Nam has made a mistake when calculating B, otherwise print "YES". If the first line is "YES", then also print mrows consisting of n integers representing matrix A that can produce given matrix B. If there are several solutions print any one.

Examples
input
2 2
1 0
0 0
output
NO
input
2 3
1 1 1
1 1 1
output
YES
1 1 1
1 1 1
input
2 3
0 1 0
1 1 1
output
YES
0 0 0
0 1 0

题解:重新定义的 “与运算” ,读懂题意就好办了

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int m,n;
bool a[110][110];
bool b[110][110];
int main()
{
	while(~scanf("%d %d",&m,&n))
	{
		for(int i=1;i<=m;i++)
		{
			for(int j=1;j<=n;j++)
			{
				scanf("%d",&b[i][j]);
				a[i][j]=1;
			}
		}
		for(int i=1;i<=m;i++)
		{
			for(int j=1;j<=n;j++)
			{
				if(!b[i][j]) // 由题意知,a 矩阵的 i行,k列所有的元素都为 0 
				{
					for(int k=1;k<=n;k++)
						a[i][k]=0;
					for(int k=1;k<=m;k++)
						a[k][j]=0;
				}
			}
		}
		bool temp=0;
		for(int i=1;i<=m;i++)
		{
			for(int j=1;j<=n;j++)
			{
				if(b[i][j])
				{
					bool flag=0;
					for(int k=1;k<=n;k++)
					{
						if(a[i][k])
						{
							flag=1;
							break;	
						}
					}
					for(int k=1;k<=m;k++)
					{
						if(a[k][j])
						{
							flag=1;
							break;
						}
					}
					if(!flag) // 找遍所有 i行,j列的元素,如果没有一个为 1,则矩阵错误 
					{
						temp=1;
						break;
					}
				}
			}
			if(temp)	break;
		}
		if(temp)	puts("NO");
		else
		{
			puts("YES");
			for(int i=1;i<=m;i++)
			{
				for(int j=1;j<=n;j++)
				{
					printf(j==1?"%d":" %d",a[i][j]);
				}
				puts("");
			}
		}
	}
	return 0;
}

题目链接: 点击打开链接

C. Palindrome Transformation
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Nam is playing with a string on his computer. The string consists of n lowercase English letters. It is meaningless, so Nam decided to make the string more beautiful, that is to make it be a palindrome by using 4 arrow keys: left, right, up, down.

There is a cursor pointing at some symbol of the string. Suppose that cursor is at position i (1 ≤ i ≤ n, the string uses 1-based indexing) now. Left and right arrow keys are used to move cursor around the string. The string is cyclic, that means that when Nam presses left arrow key, the cursor will move to position i - 1 if i > 1 or to the end of the string (i. e. position n) otherwise. The same holds when he presses the right arrow key (if i = n, the cursor appears at the beginning of the string).

When Nam presses up arrow key, the letter which the text cursor is pointing to will change to the next letter in English alphabet (assuming that alphabet is also cyclic, i. e. after 'z' follows 'a'). The same holds when he presses the down arrow key.

Initially, the text cursor is at position p.

Because Nam has a lot homework to do, he wants to complete this as fast as possible. Can you help him by calculating the minimum number of arrow keys presses to make the string to be a palindrome?

Input

The first line contains two space-separated integers n (1 ≤ n ≤ 105) and p (1 ≤ p ≤ n), the length of Nam's string and the initial position of the text cursor.

The next line contains n lowercase characters of Nam's string.

Output

Print the minimum number of presses needed to change string into a palindrome.

Examples
input
8 3
aeabcaez
output
6
Note

A string is a palindrome if it reads the same forward or reversed.

In the sample test, initial Nam's string is:  (cursor position is shown bold).

In optimal solution, Nam may do 6 following steps:

The result, , is now a palindrome.


题意:给你一个字符串,通过 left、right(指针移动)、up、down(字符变化)将它改成一个回文字符串。现在让你求最小的移动次数。


思路:因为每次操作都是移动指针或者改变字符串,所以只需要字符前半部分和后半部分进行比较。首先把需要翻转字符的首末位置、次数记录下来。如果指针不需要来回,一次就可以完成,否则,指针一定是先移动完一边在去另一边,求出最小值就可以。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n,p;
char str[100010];
int main()
{
	while(~scanf("%d %d",&n,&p))
	{
		scanf("%s",str+1);
		if(p>n/2)	p=n+1-p; // 因为下面的比较是在串的前一半进行的,要把 p等效换到左边 
		bool flag=0;
		int st,ed,ans=0;
		for(int i=1;i<=n/2;i++)
		{
			int dif=abs(str[i]-str[n+1-i]);
			if(dif)
			{
				if(!flag)
				{
					st=i; // 记录串需要改变的第一个位置 
					flag=1;
				}
				ed=i; // 记录串需要改变的最后一个位置 
				ans+=min(dif,26-dif); // 选择最优的 up/down 的次数 
			}
		}
		if(ans==0)	puts("0");
		else if(st>=p) // p在 st的左边 
			printf("%d\n",ed-p+ans);
		else if(ed<=p) // p在 ed的右边 
			printf("%d\n",p-st+ans);
		else // p在中间,需要来回移动 
			printf("%d\n",min(2*(p-st)+ed-p+ans,2*(ed-p)+p-st+ans)); // 找出移动的最优解 
	}
	return 0;
}

题目链接: 点击打开链接

D. Valid Sets
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

As you know, an undirected connected graph with n nodes and n - 1 edges is called a tree. You are given an integer d and a tree consisting of n nodes. Each node i has a value ai associated with it.

We call a set S of tree nodes valid if following conditions are satisfied:

  1. S is non-empty.
  2. S is connected. In other words, if nodes u and v are in S, then all nodes lying on the simple path between u and v should also be presented in S.
  3. .

Your task is to count the number of valid sets. Since the result can be very large, you must print its remainder modulo 1000000007 (109 + 7).

Input

The first line contains two space-separated integers d (0 ≤ d ≤ 2000) and n (1 ≤ n ≤ 2000).

The second line contains n space-separated positive integers a1, a2, ..., an(1 ≤ ai ≤ 2000).

Then the next n - 1 line each contain pair of integers u and v (1 ≤ u, v ≤ n) denoting that there is an edge between u and v. It is guaranteed that these edges form a tree.

Output

Print the number of valid sets modulo 1000000007.

Examples
input
1 4
2 1 3 2
1 2
1 3
3 4
output
8
input
0 3
1 2 3
1 2
2 3
output
3
input
4 8
7 8 7 5 4 6 4 10
1 6
1 2
5 8
1 3
3 5
6 7
3 4
output
41
Note

In the first sample, there are exactly 8 valid sets: {1}, {2}, {3}, {4}, {1, 2}, {1, 3}, {3, 4} and {1, 3, 4}. Set {1, 2, 3, 4} is not valid, because the third condition isn't satisfied. Set {1, 4} satisfies the third condition, but conflicts with the second condition.


题意:给一棵树,问它有多少子树,子树的最大权值与最小权值之差不大于d,而且非空。

思路:考虑以每个点作为根结点扩展出一棵树,这个树满足树上所有的节点的权值都不比树根大

且 val [ root ] - val [ v ] < = d,然后可以树型 DP 求以这个点为树根的集合数。如果以 u 为根时扩展的树中包含了与 u 权值相同的 v,那么以 v 为根时便不能包括 u 了,这里需要判重。两节点相等的情况可能重复考虑,规定只能从小标号到大标号或者从大标号到小标号,即可避免重复。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#define LL long long
using namespace std;
const int mod=1000000007;
int d,n,root;
int val[2010];
vector<int> G[2010];
LL dfs(int u,int fa)
{
	LL ans=1;
	int len=G[u].size();
	for(int i=0;i<len;i++)
	{
		int v=G[u][i];
		if(v==fa||val[v]>val[root]||(val[v]==val[root]&&v<root)||val[root]-val[v]>d)
			continue;
		ans=(ans*(dfs(v,u)+1))%mod;
	}
	return ans;
}
int main()
{
	while(~scanf("%d %d",&d,&n))
	{
		for(int i=1;i<=n;i++)
			scanf("%d",val+i);
		for(int i=0;i<2010;i++)
			G[i].clear();
		for(int i=1;i<n;i++)
		{
			int a,b;
			scanf("%d %d",&a,&b);
			G[a].push_back(b);
			G[b].push_back(a);	
		}
		LL ans=0;
		for(int i=1;i<=n;i++)
		{
			root=i;
			ans=(ans+dfs(i,-1))%mod;
		}
		printf("%I64d\n",ans);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值