hdu 5787 数位dp

Alice thinks an integer x is a K-wolf number, if every K adjacent digits in decimal representation of x is pairwised different.
Given (L,R,K), please count how many K-wolf numbers in range of L,RL,R.
Input
The input contains multiple test cases. There are about 10 test cases.

Each test case contains three integers L, R and K.

1≤L≤R≤1e181≤L≤R≤1e18
2≤K≤52≤K≤5
Output
For each test case output a line contains an integer.
Sample Input
1 1 2
20 100 5
Sample Output
1
72

题意:求区间[L,R]内,任意相邻k位(如果位数不足k,就是全部的数位)没有两两相同的数位的数的个数。

一开始开了二维的 只记录了长度,后来发现这个记忆化里面必须有上一位的信息,不然 会产生冲突,000012×××的值会加到00122××的值里面 导致结果不准确,而且k的位数很少,所以可以全记录起来 5维dp,还有就是因为用的是全记录的方法所以就没有了长度这东西,必须每次清空。当然你也可以像我这样再开一维记录长度

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int vis[20][20];
ll dp[20][20][11][11][11][11];
ll pos[29];
int num[30];
int tot;
int k;

int check(int now,int x1,int x2,int x3,int x4)
{
    if(k==2)
        return now!=x4;
    if(k==3)
        return now!=x3&&now!=x4;
    if(k==4) return now!=x2&&now!=x3&&now!=x4;
    if(k==5) return now!=x1&&now!=x3&&now!=x4&&now!=x2;
    return 0;
}

ll dfs(int pos,int zero,int p1,int p2,int p3,int p4,int flag)
{
    if(pos<0) return p4!=10&&(!zero);

    if(!zero&&!flag&&dp[pos][k][p1][p2][p3][p4]!=-1) return dp[pos][k][p1][p2][p3][p4];

    int up=flag?num[pos]:9;
    ll res=0;
    for(int i=0;i<=up;i++)
    {
        if(zero&&(i==0))
            res+=dfs(pos-1,zero,p1,p2,p3,p4,flag&&i==up);
        else
        {
            if(!check(i,p1,p2,p3,p4)) continue;
            else {
                res+=dfs(pos-1,0,p2,p3,p4,i,flag&&i==up);
            }
        }
    }
    if(!flag&&!zero)
        dp[pos][k][p1][p2][p3][p4]=res;
    return res;
}

ll solve(ll x,int k)
{
    tot=0;
    while(x){
        num[tot++]=x%10;
        x/=10;
    }
    ll res=0;
    res=dfs(tot-1,1,10,10,10,10,1);
    return res;
}

int main()
{
    ll l ,r;
    memset(dp,-1,sizeof(dp));
    while(cin>>l>>r>>k)
    {
        printf("%lld\n",solve(r,k)-solve(l-1,k));
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值