SGU 160.Magic Multiplying Machine

时间限制:0.5s

空间限制6M

题意:

       给出n个(1<=n<=10000)1~m(2<m<1000)范围内的数,选择其中任意个数,使它们的 乘积 模m 最大,输出最大的分数,和选择的数的编号。

 

 

 

 

 

 


 

Solution:

              DP,

              从第一个数开始,f[]记录当前有哪些数可以得到.如果k可以得到令f[k]=1;

              再记录路径,和更新ans。

              如果单纯使用二重循环将是N*M 的复杂度。有很大可能超过0.5s的时限。

              于是这里使用数组实现的记录了哪些数可以得到的链表,p是链表头。

code(31ms AC)

 

#include<cstdio>
int n, m, x;
int g[10009], pr[1009][2], f[1009][2];
void write (int x) {
	if (pr[x][0] != 0) write (pr[x][0]);
	printf ("%d ", pr[x][1]);
}
int main() {
	scanf ("%d %d", &n, &m);
	for (int i = 1; i <= n; i++) scanf ("%d", &x), g[i] = x % m;
	int p = 0, ans = 0;
	for (int i = 1; i <= n; i++) {
		for (int j = p; j != 0; j = f[j][1]) {
			int tem = (g[i] * j) % m;
			if (tem > 1 && !f[tem][0]) {
				f[tem][0] = 1; f[tem][1] = p;
				p = tem, pr[tem][0] = j, pr[tem][1] = i;
				if (tem > ans) ans = tem;
			}
		}
		if (!f[g[i]][0]) {
			f[g[i]][0] = 1, f[g[i]][1] = p;
			p = g[i], pr[g[i]][1] = i;
			if (g[i] > ans) ans = g[i];
		}
	}
	if (ans > 0) {
		printf ("%d\n", ans);
		write (ans);
		return 0;
	}
	puts ("1");
	return 0;
}

  

 

  

 

posted @ 2014-08-11 15:54  keambar  阅读(255)  评论(0编辑  收藏  举报