百练/ 北京大学2016研究生推免上机考试(校外)E: Divisibility(动态规划)

题目来源:http://poj.org/problem?id=1745

Divisibility

Time Limit: 1000MS

Memory Limit: 10000K

Description

Consider an arbitrary sequence of integers. Onecan place + or - operators between integers in the sequence, thus derivingdifferent arithmetical expressions that evaluate to different values. Let us,for example, take the sequence: 17, 5, -21, 15. There are eight possibleexpressions: 17 + 5 + -21 + 15 = 16 
17 + 5 + -21 - 15 = -14 
17 + 5 - -21 + 15 = 58 
17 + 5 - -21 - 15 = 28 
17 - 5 + -21 + 15 = 6 
17 - 5 + -21 - 15 = -24 
17 - 5 - -21 + 15 = 48 
17 - 5 - -21 - 15 = 18 
We call the sequence of integers divisible by K if + or - operators can beplaced between integers in the sequence in such way that resulting value isdivisible by K. In the above example, the sequence is divisible by 7(17+5+-21-15=-14) but is not divisible by 5. 

You are to write a program that will determine divisibility of sequence ofintegers. 

Input

The first line of the input file contains twointegers, N and K (1 <= N <= 10000, 2 <= K <= 100) separated by aspace. 
The second line contains a sequence of N integers separated by spaces. Eachinteger is not greater than 10000 by it's absolute value. 

Output

Write to the output file the word"Divisible" if given sequence of integers is divisible by K or"Not divisible" if it's not.

Sample Input

4 7
17 5 -21 15

SampleOutput

扫描二维码关注公众号,回复: 1060474 查看本文章
Divisible

Source

Northeastern Europe 1999

-----------------------------------------------------

解题思路

动态规划(0-1背包)

题目本身的坑点在于C/C++里 -20%7 = -6而不是1,需要+7化成正数

值得注意的是之前一直听说但从来没有遇到过的”cin vs. scanf””int a[10001] vs. int *a = new int*[n]”前者速度慢于后者的情况终于发生了。

百练上的数据比较弱,用后面的写法也能过。poj上的数据比较严,一定要直接开固定大小的数组才能过,动态分配数组过不了;用cin也能过,但cin版本用时797ms, scanf版本用时297ms,差了500ms!太可怕了!

血泪教训:

1. 如果题目告诉了数据个数的上限,直接按上限开固定大小的数组;

2. 如果要从标准输入流中读取大量数据,用scanf不要用cin.

-----------------------------------------------------

代码

//E:Divisibility
//总时间限制: 1000ms 内存限制: 65536kB
//描述
//Consider an arbitrary sequence of integers. One can place + or - operators between integers in the sequence, thus deriving different arithmetical expressions that evaluate to different values. Let us, for example, take the sequence: 17, 5, -21, 15. There are eight possible expressions: 17 + 5 + -21 + 15 = 16 
//17 + 5 + -21 - 15 = -14 
//17 + 5 - -21 + 15 = 58 
//17 + 5 - -21 - 15 = 28 
//17 - 5 + -21 + 15 = 6 
//17 - 5 + -21 - 15 = -24 
//17 - 5 - -21 + 15 = 48 
//17 - 5 - -21 - 15 = 18 
//We call the sequence of integers divisible by K if + or - operators can be placed between integers in the sequence in such way that resulting value is divisible by K. In the above example, the sequence is divisible by 7 (17+5+-21-15=-14) but is not divisible by 5. 
//
//You are to write a program that will determine divisibility of sequence of integers. 
//输入
//The first line of the input file contains two integers, N and K (1 <= N <= 10000, 2 <= K <= 100) separated by a space. 
//The second line contains a sequence of N integers separated by spaces. Each integer is not greater than 10000 by it's absolute value. 
//输出
//Write to the output file the word "Divisible" if given sequence of integers is divisible by K or "Not divisible" if it's not.
//样例输入
//4 7
//17 5 -21 15
//样例输出
//Divisible

#include<fstream>
#include<iostream>
#include<stdio.h>
using namespace std;

int main()
{
#ifndef ONLINE_JUDGE
	ifstream fin("tm201602E.txt");
	int n,k,i,j;
	fin >> n >> k;
	int *num = new int[n];
	for (i=0; i<n; i++)
	{
		fin >> num[i];
		num[i] %= k;
		if (num[i]<0)							// 防止出现负数
		{
			num[i] += k;
		}
	}
	int **dp = new int*[n];
	for (i=0; i<n; i++)
	{
		dp[i] = new int[k]();
	}
	// dynamic programming
	dp[0][num[0]] = 1;
	for (i=1; i<n; i++)
	{
		for (j=0; j<k; j++)
		{
			if (dp[i-1][j])
			{
				dp[i][(j+num[i])%k] = 1;
				dp[i][(j-num[i]+k)%k] = 1;		// 防止出现负数
			}

		}

	}
	if (dp[n-1][0] == 1)
	{
		cout << "Divisible";
	}
	else
	{
		cout << "Not divisible";
	}
	delete[] num;
	for (i=0; i<n; i++)
	{
		delete[] dp[i];
	}
	delete[] dp;
	fin.close();
#endif
#ifdef ONLINE_JUDGE
	int n,k,i,j,tmp;
	cin >> n >> k;
	int num[10001];        // 开固定大小数组
	for (i=0; i<n; i++)
	{
		cin >> num[i]; // 这里用cin也能过,但最好用scanf
		num[i] %= k;
		if (num[i]<0)
		{
			num[i] += k;
		}
	}
	int dp[10001][100] = {} ;
	// dynamic programming
	dp[0][num[0]] = 1;
	for (i=1; i<n; i++)
	{
		for (j=0; j<k; j++)
		{
			if (dp[i-1][j])
			{
				dp[i][(j+num[i])%k] = 1;
				dp[i][(j-num[i]+k)%k] = 1;
			}

		}

	}
	if (dp[n-1][0] == 1)
	{
		cout << "Divisible";
	}
	else
	{
		cout << "Not divisible";
	}
#endif
}


猜你喜欢

转载自blog.csdn.net/da_kao_la/article/details/80268917
今日推荐