HDU 3709 平衡数 数位dp(Java版)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3709
题目大意:选取某一个数字作为支点,各个数字到该数字的距离为力矩,使得杠杆平衡。如3218这个数,以1为支点时,3距离为2,2距离为1,左边之和为8,后边之和也为8,为平衡数,求在[x,y]范围内平衡数的数量。

只要枚举每个支点的位置,其他的是个裸数位dp,感觉自己又理解了一点,哈哈哈

另外,这个题是做到的第一个前导0有影响的题
如果数为0,是可以的(既符合题意,又确实存在这个数)
如果数为00,是不可以的(符合题意,是平衡数,但是这个数跟0不是一个吗)
所以这个数有几位,数位最大是len,就会多统计了len-1个,在计算的时候要除掉
AC代码:

import java.util.Scanner;

public class Main {
	static int a[]=new int[20];
	static long dp[][][]=new long[20][20][2050];
	static long solve(long x){
		int pos=0;
		long ans=0;
		while(x!=0){
			a[++pos]=(int) (x%10);
			x/=10;
		}
		for(int i=1;i<=pos;i++){
			ans+=dfs(pos,i,0,true);
		}
		return ans-pos+1;
	}
	//pos为当前枚举的数位,x为平衡点的位置,st为左边点到平和点的力矩和,limit代表是否枚举到了上限
	static long dfs(int pos,int x,int st,boolean limit){
		if(pos==0)
			return st==0?1:0;
		if(st<0)
			return 0;
		if(!limit&&dp[pos][x][st]!=-1)
			return dp[pos][x][st];
		int num=(limit?a[pos]:9);
		long ans=0;
		for(int i=0;i<=num;i++){
			int tmp=st+i*(pos-x);
			ans+=dfs(pos-1,x,tmp,limit&&i==a[pos]);//保存左边点到平和点的力矩和为tmp的状态数量
		}
		if(!limit)
			dp[pos][x][st]=ans;
		return ans;
	}
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		for(int i=0;i<dp.length;i++){
			for(int j=0;j<dp[i].length;j++){
				for(int k=0;k<dp[i][j].length;k++){
					dp[i][j][k]=-1;
				}
			}
		}
		int t=sc.nextInt();
		while(t-->0){
			long x=sc.nextLong();
			long y=sc.nextLong();
			System.out.println(solve(y)-solve(x-1));
		}
		sc.close();
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值