hdu6148 数位dp

传送门
题意:求区间内 数字是V型 的数字个数,这是套路题,dp[i][j][k],表示第i位前一位是j状态位K的数字个数,这基本都是套路,状态k就两种,1表示递增,0表示非递增,然后其他 的都是套路的东西,dfs(int pos,int pre,int sta,int limit),pos当前位,pre上一位的值,sta K的状态,limit 上一位是否是 上界,每次根据sta的状态来跑,sta==1时,是上升的状态,那么当前位只能从pre 开始跑,如果是下降的,那么就分,当i>pre
时,变成上升的状态,其他的仍是下降的状态。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
typedef long long LL;
const int MAXN = 1e6+5;
const double PI = acos(-1);
const double eps = 1e-8;
const int MOD = 1e9+7;
inline int GCD(int a, int b)
{
    if(b  == 0) return a;
    return GCD(b, a%b);
}
inline LL GCD(LL a, LL b)
{
    if(b  == 0) return a;
    return GCD(b, a%b);
}
inline int LCM(int a, int b)
{
    return a/GCD(b, a%b)*b;
}
inline LL LCM(LL a, LL b)
{
    return a/GCD(b, a%b)*b;
}
namespace IO
{
const int MX = 4e7; //1e7占用内存11000kb
char buf[MX];
int c, sz;
void begin()
{
    c = 0;
    sz = fread(buf, 1, MX, stdin);
}
inline bool read(int &t)
{
    while(c < sz && buf[c] != '-' && (buf[c] < '0' || buf[c] > '9')) c++;
    if(c >= sz) return false;
    bool flag = 0;
    if(buf[c] == '-') flag = 1, c++;
    for(t = 0; c < sz && '0' <= buf[c] && buf[c] <= '9'; c++) t = t * 10 + buf[c] - '0';
    if(flag) t = -t;
    return true;
}
}

char n[105];
int len;
LL dp[105][15][15];
LL bit[105];
LL dfs(int pos,int pre,int sta,int work)
{
    if(pos<1)
        return 1;
    if(!work&&~dp[pos][pre][sta])
        return dp[pos][pre][sta];
    int end0= work ? bit[pos] : 9;
    LL ans=0;
    if(sta)
    {
        for(int i=pre; i<=end0; i++)
        {
            ans+=dfs(pos-1,i,sta,work&&i==end0);
            ans%=MOD;
        }
    }
    else
    {
        for(int i=0; i<=end0; i++)
        {
            if(i>pre)
            {
                ans+=dfs(pos-1,i,1,work&&i==end0);
                ans%=MOD;
            }
            else
            {
                if(!i&&pre==10)
                    ans+=dfs(pos-1,10,0,work&&i==end0);
                else
                    ans+=dfs(pos-1,i,0,work&&i==end0);
                ans%=MOD;
            }
        }
    }
    if(!work)
        dp[pos][pre][sta]=ans;
    return ans;
}
int main()
{
    int T;
    cin>>T;
    memset(dp,-1,sizeof(dp));
    while(T--)
    {
        cin>>n;
        len=strlen(n);
        for(int i=0; i'0';
        printf("%lld\n",dfs(len,10,0,1)-1LL);
    }
    return 0;
}

你可能感兴趣的:(-------数位dp)