About [NOIP2003 普及组] 数字游戏
题目描述
丁丁最近沉迷于一个数字游戏之中。这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易。游戏是这样的,在你面前有一圈整数(一共 nn 个),你要按顺序将其分为 mm 个部分,各部分内的数字相加,相加所得的 mm 个结果对 1010 取模后再相乘,最终得到一个数 kk。游戏的要求是使你所得的 kk 最大或者最小。
例如,对于下面这圈数字(n=4n=4,m=2m=2):

要求最小值时,((2-1)\bmod10)\times ((4+3)\bmod10)=1\times 7=7((2−1)mod10)×((4+3)mod10)=1×7=7,要求最大值时,为 ((2+4+3)\bmod10)\times (-1\bmod10)=9\times 9=81((2+4+3)mod10)×(−1mod10)=9×9=81。特别值得注意的是,无论是负数还是正数,对 1010 取模的结果均为非负值。
丁丁请你编写程序帮他赢得这个游戏。
输入格式
输入文件第一行有两个整数,nn (1\le n\le 501≤n≤50) 和 mm (1\le m\le 91≤m≤9)。以下 nn 行每行有个整数,其绝对值 \le10^4≤104,按顺序给出圈中的数字,首尾相接。
输出格式
输出文件有 22 行,各包含 11 个非负整数。第 11 行是你程序得到的最小值,第 22 行是最大值。
输入输出样例
输入 #1
4 2 4 3 -1 2
输出 #1
7 81
说明/提示
【题目来源】
NOIP 2003 普及组第二题
序列型dp
环形自然想到把数组复制一遍
以每个数字做开头来dp一遍
#include <bits/stdc++.h>
using namespace std;
const int N = 105, inf = 2e9;
int n, m, a[N];
int f[N][N][10], g[N][N][10];
inline int mod(int x) {return (x % 10 + 10) % 10;}
int main(){
	cin >> n >> m;
	for (int i = 1; i <= n; i++) cin >> a[i], a[i + n] = a[i];
	for (int i = 1; i <= n * 2; i++) a[i] += a[i - 1];
	memset(f, 0x3f, sizeof f);
	for (int i = 1; i <= n * 2; i++)
		for (int j = i; j <= n * 2; j++)
			f[i][j][1] = g[i][j][1] = mod(a[j] - a[i - 1]);
	for (int st = 1; st <= n * 2; st++){
		for (int i = 1; i <= n * 2; i++){
			for (int j = 2; j <= m; j++){
				for (int k = st + j - 2; k < i; k ++ ){
					f[st][i][j] = min(f[st][i][j], f[st][k][j - 1] * mod(a[i] - a[k]));
					g[st][i][j] = max(g[st][i][j], g[st][k][j - 1] * mod(a[i] - a[k]));
				}
			}
		}
	}
	int minv = inf, maxv = -inf;
	for (int i = 1; i <= n; i++){
		minv = min(minv, f[i][i + n - 1][m]);
		maxv = max(maxv, g[i][i + n - 1][m]);
	}
	cout << minv << endl << maxv << endl;
	return 0;
}
一点点指针的运用
而且数据这么水随便搞搞都能过
                    
                
                
            
        
浙公网安备 33010602011771号