按位dp Balanced Number

题意:首先给出Balanced Number 的定义, Balanced Number是指一个数中选择一个位为支点, 然后按照天平的计算方法,如果左边和右边相等, 那么这个数就是一个Balanced Number,(例如4139 is a balanced number with pivot fixed at 3. The torqueses are 4*2 + 1*1 = 9 and 9*1 = 9),否则就不是。现在给出了一个区间让求出这个区间中的Balanced Number的个数。区间的范围为10^18.

 

思路: 这道题一开始的时候就像到了用数位dp。

开始想的是dp[now][sum][p][have] ,表示当前的状态为now, 前方的值为sum,当前在第p位, have表示是否已经经历了支点。 这样的话数组开不够。 现在发现其实可以少一维,将u那一维少了也不影响。

 

后来我的dp方程是这样开的,dp[now][p][w],表示当前的状态为now, 当前站在p点,支点为w。now可能为负值,因此可以加上一个常数N。 这样的话就可以往下边dp了,只不过求的时候要枚举起点。对了值得一说的是这里有一个剪枝,当now <0 && p < w时就可以直接return 0了。

后来交的时候wa了一次, 主要是我把0没有算成Balanced Number。

下面是代码:

 

View Code
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
typedef long long LL;
const int N = 1610;

LL dp[2*N][19][19], a, b;
int num[20], pos;

LL dfs(int now, int p, int w, bool istop)
 {
     if(p == -1)
      {
          if(now == 0) return 1;
          return 0;
      }
     if(now < 0 && p < w) return 0;
     if(!istop &&  dp[now+N][p][w] != -1)
      {
          return dp[now+N][p][w];
      }
     int top = istop ? num[p]:9;
     LL ans = 0;
     for(int i=0; i<=top; i++)
      {
          if(p > w)
           {
               ans += dfs(now+(p-w)*i,p-1,w,istop&&i==top);
           }
          if(p == w)
           {
               ans += dfs(now, p-1, w, istop&&i==top);
           }
          if(p < w)
           {
               ans += dfs(now-(w-p)*i, p-1,w,istop&&i==top);
           }
      }
     if(!istop && dp[now+N][p][w] == -1)
      {
          dp[now+N][p][w] = ans;
      }
    return ans;
 }

LL get(LL n)
 {
     if(n < 0) return 0;
     LL ans = 0;
     pos = 0;
     while(n)
      {
          num[pos++] = n%10;
          n /= 10;
      }
     for(int i=0; i<=pos-1; i++)
     {
         ans += dfs(0,pos-1,i,1);
     }
    ans -= pos-1;
    return ans;
 }

int main()
{
    int t;
    LL ans;
    memset(dp, -1, sizeof(dp));
    scanf("%d", &t);
    while(t--)
     {
         scanf("%lld%lld", &a, &b);
         if(a > b) swap(a, b);
         ans = get(b) - get(a-1);
         printf("%lld\n", ans);
     }
    return 0;
}

 

 

 

 

posted @ 2012-09-26 17:08  Gu Feiyang  阅读(160)  评论(0)    收藏  举报