Codeforces Round #157 (Div. 1)B 数位dp -电脑资料

电脑资料 时间:2019-01-01 我要投稿
【www.unjs.com - 电脑资料】

    //枚举有几个(7或4),用数位dp的记忆化搜索找有i个(7或4)的数又多少个

    //暴力搜索在第i个中选几个

    #include

    #include

    #include

    using namespace std ;

    const int mod = 1e9 + 7;

    int dp[20][20];//第i位有 j个数(7或者4)

    int bit[20] ;

    int temp[20];

    int luck[20];

    int dfs(int pos , int flag ,int max_flag, int lim)

    {

    if(pos == 0)

    return flag == max_flag;

    if(!lim && dp[pos][flag] != -1)

    return dp[pos][flag] ;

    int num = lim ? bit[pos] : 9;

    int ans = 0 ;

    for(int i = 0;i <= num ;i++)

    {

    int flag_x = flag ;

    if(i == 7 || i == 4)

    flag_x++;

    ans += dfs(pos - 1 ,flag_x ,max_flag, lim && (i==num)) ;

    }

    if(!lim)dp[pos][flag] = ans ;

    return ans ;

    }

    //__int64 ans_ans = 0;

    __int64 dfs_s(int res , __int64 ans ,int pos, int num ,int max_flag)

    {

    if(num >= max_flag)

    return 0;

    if(res == 0)

    return (ans * (__int64)temp[num+1])%mod;

    __int64 sum = 0;

    for(int i = 0 ;i <= pos;i++)

    {

    if(luck[i] > 0)

    {

    __int64 ans_x = ((ans*(__int64)luck[i])%mod);

    luck[i] -= 1;

    sum += dfs_s(res - 1 , ans_x , pos , num+i , max_flag) ;

    luck[i] += 1;

    }

    }

    return sum%mod;

    }

    __int64 solve(int n)

    {

    if(n == 7)return 0;

    int t = n;

    int pos = 0;

    while(t)

    {

    bit[++pos] = t%10 ;

    t/=10 ;

    }

    memset(luck , 0 ,sizeof(luck)) ;

    memset(temp , 0 , sizeof(temp));

    for(int i = pos;i >= 0 ;i--)

    {

    memset(dp , -1 , sizeof(dp)) ;

    luck[i] = dfs(pos , 0 , i , 1) ;

    temp[i] = temp[i+1] + luck[i];

    }

    luck[0] -= 1;

    return dfs_s(6 , 1 , pos , 0 , luck[pos] ? pos : pos - 1) ;

    }

    int main()

    {

    // freopen("input.txt" ,"r" ,stdin) ;

    int n ;

    while(~scanf("%d" ,&n))

    {

    printf("%I64d\n" ,solve(n)%mod) ;

    }

    return 0;

    }

最新文章