码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 4351

时间:2015-02-02 22:52:06      阅读:249      评论:0      收藏:0      [点我收藏+]

标签:

求某区间各个子集的和的根的最大的五个数。

子集根其实就是这个数模9后的余数,注意的是要区分0和9,两者的余数都是0。、

记录前i个数的和的根,设为sum数组,然后处理两个数组

lft[i][j]表示从i开始往右,最先sum出现根为j的位置。

rht[i][j]表示从i开始往左,最先sum开始出现根为j的位置。

处理一次询问,可以枚举状态,如枚举到j,当lft[i][j]<rht[i][j+k]成立时,则表明k这个根是存在的。

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

const int MAX=101000;

int number[MAX],zero[MAX],lft[MAX][11],rht[MAX][11];
int cnt[MAX];
int sum[MAX],cts;
int res[10];

int f(int m){
	if(m==0) return 0;
	else if((m%9)==0)
	return 9;
	else return (m%9);
}

int main(){
	int T,n,tmp,kase=0;
	scanf("%d",&T);
	while(T--){
		printf("Case #%d:\n",++kase);
		scanf("%d",&n);
		sum[0]=zero[0]=0;
		cnt[0]=0;
		for(int i=1;i<=n;i++){
			scanf("%d",&tmp);
			sum[i]=f(sum[i-1]+tmp);
			cnt[i]=tmp==0?cnt[i-1]:cnt[i-1]+1;
			zero[i]=tmp==0?i:zero[i-1];
		}
		cnt[n+1]=cnt[n]+1;
		for(int i=0;i<=9;i++)lft[n+1][i]=n+1,rht[0][i]=0;
		for(int i=n;i>=0;i--){
			for(int k=0;k<=9;k++){
				if(sum[i]==k)
				lft[i][k]=i;
				else lft[i][k]=lft[i+1][k];
			}
		}
		for(int i=1;i<=n;i++){
			for(int k=0;k<=9;k++){
				if(sum[i]==k)
				rht[i][k]=i;
				else rht[i][k]=rht[i-1][k];
			}
		}
		int qy,x,y,a,b;
		scanf("%d",&qy);
		while(qy--){
			scanf("%d%d",&x,&y);
			memset(res,-1,sizeof(res));
			for(int i=9,cts=5;i>0&&cts>0;i--){
				int k;
				for(k=0;k<=9;k++){
					a=k;
					b=a+i;
					if(b>9) b-=9;
					if(cnt[lft[x-1][a]]<cnt[rht[y][b]]) break;
				}
				if(k<=9) res[cts--]=i;
			}
			if(cts>0){
				if(zero[y]>=x) res[cts--]=0;
			}
			printf("%d",res[5]);
			for(int i=4;i>0;i--)
			printf(" %d",res[i]);
			printf("\n");
		}
		if(T>0)
		printf("\n");
	}
	return 0;
}

  

HDU 4351

标签:

原文地址:http://www.cnblogs.com/jie-dcai/p/4268855.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!