SPOJ BALNUM

Posted on 2016-12-22 19:12  ziliuziliu  阅读(94)  评论(0编辑  收藏  举报

一开始题看错了。。。dp[pos][sets][viss],其中sets表示出现次数,viss表示出现没有。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
long long t,l,r,dp[22][1025][1025],bit[22],ret=0;
void get_bit(long long x)
{
    ret=0;
    while (x) {bit[++ret]=x%10;x/=10;}
}
long long check(long long sets,long long viss)
{
    for (long long i=0;i<=9;i++)
    {
        if (!(viss&(1<<i))) continue;
        if ((i&1) && (sets&(1<<i))) return 0;
        if ((!(i&1)) && (!(sets&(1<<i)))) return 0;
    }
    return 1;
}
long long dfs(long long pos,long long sets,long long viss,bool flag)
{
    if (!pos) return check(sets,viss);
    if ((!flag) && (~dp[pos][sets][viss])) return dp[pos][sets][viss];
    long long ans=0,up=flag?bit[pos]:9;
    for (long long i=0;i<=up;i++)
        ans+=dfs(pos-1,sets^(1<<i),viss|(1<<i),flag&&(i==up));
    if (!flag) dp[pos][sets][viss]=ans;
    return ans;
}
long long work(long long x)
{
    if (!x) return 0;
    get_bit(x);long long ans=0;
    for (long long i=1;i<=ret-1;i++)
        for (long long j=1;j<=9;j++)
            ans+=dfs(i-1,1<<j,1<<j,0);
    for (long long j=1;j<=bit[ret]-1;j++)
        ans+=dfs(ret-1,1<<j,1<<j,0);
    ans+=dfs(ret-1,1<<bit[ret],1<<bit[ret],1);
    return ans;
}
int main()
{
    scanf("%lld",&t);memset(dp,-1,sizeof(dp));
    for (long long i=1;i<=t;i++)
    {
        scanf("%lld%lld",&l,&r);
        printf("%lld\n",work(r)-work(l-1));
    }
    return 0;
}