zoukankan      html  css  js  c++  java
  • Codeforces Round #131 (Div. 1) B. Numbers dp

    题目链接:

    http://codeforces.com/problemset/problem/213/B

    B. Numbers

    time limit per test 2 seconds
    memory limit per test 256 megabytes
    #### 问题描述 > Furik loves writing all sorts of problems, especially such that he can't solve himself. You've got one of his problems, the one Furik gave to Rubik. And Rubik asks you to solve it. > > There is integer n and array a, consisting of ten integers, indexed by numbers from 0 to 9. Your task is to count the number of positive integers with the following properties: > > the number's length does not exceed n; > the number doesn't have leading zeroes; > digit i (0 ≤ i ≤ 9) occurs in the number at least a[i] times. #### 输入 > The first line contains integer n (1 ≤ n ≤ 100). The next line contains 10 integers a[0], a[1], ..., a[9] (0 ≤ a[i] ≤ 100) — elements of array a. The numbers are separated by spaces. #### 输出 > On a single line print the remainder of dividing the answer to the problem by 1000000007 (109 + 7). #### 样例 > **sample input** > 3 > 1 1 0 0 0 0 0 0 0 0 > > **sample output** > 36

    note

    numbers 10, 110, 210, 120, 103 meet the requirements. There are other suitable numbers, 36 in total.

    题意

    给你0到9这十个数字,第i个数至少要用a[i]次,问能拼成的长度小于等于n的正整数(不能有前导零)

    题解

    dp[i][len]表示利用i到9的数字能拼成的长度为len的所有可能数。
    状态转移方程:dp[i][len]=sigma(dp[i+1][len-k]*C[len][k])。
    相当于是在用i+1到9凑成的长度为len-k的数字串里面塞进去k个i的所有可能数。用乘法原理可知去掉已经统计出来的len-k,我们要处理的就是从len里面选k个位置来放i。
    注意:由于前导零不用考虑,而且只要统计正整数,所以我们在放0的时候,是不能让零放在第一位的,对于0我们可以特殊处理一下。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    typedef __int64 LL;
    
    const int maxn = 111;
    const int mod = 1e9 + 7;
    
    int dig[22],n;
    LL dp[22][maxn];
    
    LL C[maxn][maxn];
    void pre() {
    	memset(C, 0, sizeof(C));
    	C[0][0] = 1;
    	for (int i = 1; i < maxn; i++) {
    		C[i][0] = 1;
    		for (int j = 1; j <= i; j++) {
    			C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
    			C[i][j] %= mod;
    		}
    	}
    }
    
    int main() {
    	pre();
    	scanf("%d", &n);
    	for (int i = 0; i < 10; i++) {
    		scanf("%d", &dig[i]);
    	}
    	memset(dp, 0, sizeof(dp));
    	dp[10][0] = 1;
    	for (int i = 9; i > 0; i--) {
    		for (int j = 0; j < maxn; j++) {
    			for (int k = dig[i]; k <=j; k++) {
    				dp[i][j] += dp[i + 1][j - k] * C[j][k];
    				dp[i][j] %= mod;
    			}
    		}
    	}
    	for (int j = 0; j < maxn; j++) {
    		for (int k = dig[0]; k < j; k++) {
    			dp[0][j] += dp[1][j - k] * C[j - 1][k];
    			dp[0][j] %= mod;
    		}
    	}
    	LL ans = 0;
    	for (int j = 1; j <= n; j++) {
    		ans += dp[0][j];
    		ans %= mod;
    	}
    	printf("%I64d
    ", ans);
    	return 0;
    }
  • 相关阅读:
    0001_two_sum
    shell 命令
    先验概率,后验概率,似然函数,最大似然估计【待整理】
    numpy学习笔记
    python: __slots__ 解析 (待整理)
    ubuntu,win7双系统问题
    安装sogou输入法
    pytorch安装
    稀疏向量的一些内容
    extern c
  • 原文地址:https://www.cnblogs.com/fenice/p/5701688.html
Copyright © 2011-2022 走看看