HDU 3709 数位dp

来源:互联网 发布:大数据相关的技术 编辑:程序博客网 时间:2024/06/05 21:54

本题只需枚举中轴位置,然后数位dp即可

PS:注意00,000这些都不能算进去,要单独去掉(因为在不同的中轴线下,这些数会算多次0,导致结果错误)

#include <bits/stdc++.h>using namespace std;#define ll long longconst ll maxn = 20;ll dp[maxn][4000][maxn];ll a[maxn];ll dfs(int pos, int state, int mid, bool lead, bool limit){if(pos < 0) return state == 2000;//printf("pos:  %d mid:  %d\n",pos,mid);//printf("dp[pos][state][mid]:  dp[%d][%d][%d] = %d\n",pos,state,mid,dp[pos][state][mid]);if(!limit && !lead && dp[pos][state][mid] != -1) return dp[pos][state][mid];//printf("pos2:  %d mid2:  %d\n",pos,mid);int up = limit ? a[pos] : 9;ll ans = 0;for(int i = 0;i <= up;i++){//printf("pos:  %d\n",pos);if(lead && i == 0 && pos == 0) continue;ans += dfs(pos - 1,state + (pos - mid) * i,mid,lead && (i == 0),limit && (i == up));\//printf("ansbbb:  %d\n",ans);}if(!limit && !lead) dp[pos][state][mid] = ans;return ans;}ll solve(ll x){int pos = 0;if(x <= 0) return 0;while(x > 0){a[pos++] = x % 10;x = x / 10;}ll ans = 0;for(int i = 0;i < pos;i++){//memset(dp,-1,sizeof(dp));ans += dfs(pos - 1,2000,i,true,true);//因为state要大于0,所以设2000表示0 //printf("ans:  %d\n",ans);}return ans;}int main(){//freopen("hdu3709.in","r",stdin); int kase;scanf("%d",&kase);memset(dp,-1,sizeof(dp));while(kase--){ll a,b;scanf("%I64d%I64d",&a,&b);int add = a == 0 ? 1 : 0;printf("%I64d\n",solve(b) - solve(a-1) + add);}return 0;}


原创粉丝点击