zoukankan      html  css  js  c++  java
  • hdu 3709 Balanced Number 数位dp

    题目链接

    一个数称为平衡数, 只要他的某一位满足, 这一位左边的所有数sigma x*(x距离这一位的距离)等于右边的sigma x*(x距离这一位的距离), 例如4139, 3就满足这个性质, 因为4*2+1*1 == 9*1。

    求出一个范围内的平衡数的数量。

    看起来好麻烦, 不好想状态, 但是我们可以枚举每一位作为支点, 这样问题就简化了许多。具体看代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 #define mem1(a) memset(a, -1, sizeof(a))
     5 ll dp[20][20][4000], digit[20];
     6 ll dfs(int len, int center, int sum, bool fp) {
     7     if(!len) {
     8         return sum==0;
     9     }
    10     if(!fp&&dp[len][center][sum]!=-1)           //center是支点, sum是和
    11         return dp[len][center][sum];
    12     ll maxx = fp?digit[len]:9, ret = 0;
    13     for(int i = 0; i<=maxx; i++) {
    14         ret += dfs(len-1, center, sum+i*(center-len), fp&&i==maxx);
    15     }
    16     if(!fp)
    17         return dp[len][center][sum] = ret;
    18     return ret;
    19 }
    20 ll cal(ll n) {
    21     int len = 0;
    22     while(n) {
    23         digit[++len] = n%10;
    24         n/=10;
    25     }
    26     ll ret = 0;
    27     for(int i = 1; i<=len; i++) {
    28         ret += dfs(len, i, 0, 1);           //枚举每一位
    29     }
    30     return ret-(len-1);         //因为每次计算了len个0, 而我们只需要一个0
    31 }
    32 int main()
    33 {
    34     ll a, b, t;
    35     mem1(dp);
    36     cin>>t;
    37     while(t--) {
    38         scanf("%I64d%I64d", &a, &b);
    39         printf("%I64d
    ", cal(b)-cal(a-1));
    40     }
    41 }
  • 相关阅读:
    Codevs 1283 等差子序列
    Codevs 1282 约瑟夫问题
    Codevs 1228 苹果树
    Codevs 1191 数轴染色
    洛谷P1080 国王游戏
    Codevs 1523 地精部落
    2014-7-17 NOIP模拟赛
    Codevs 3409 搬运礼物
    Codevs 1425 最长公共子串
    TyvjP1863 [Poetize I]黑魔法师之门(2014-8-27)
  • 原文地址:https://www.cnblogs.com/yohaha/p/5036792.html
Copyright © 2011-2022 走看看