Password Attacker

题意就是给 M 个关键字,组合成 N 字符长度的结果,每一个关键字都必须在 N 位的字符中出现,有多少种可能结果。

范围 1 ≤ M ≤ N ≤ 100.

举例假设 M = 3(key = 3, 7, 5)  N = 4 位字符长度

结果可以为3577, 3557, 7353, 5735.

下面的结果是不合法的

1357 // 1 没有在key中,不是合法关键字

3355 // 7 是关键字,但是结果中没有出现

357 // 结果必须是一个4位长度

思路1:

设立状态dp(i, j)表示在 M 个关键字中取前 i 个不同关键字,组成长度为 j . 所有结果总和

划分子问题

1. i == j 时候, 取前 i 个Key组成长度为 i ,结果为

2. i < j 时候,考虑dp(i-1, k),选去第 i 个元素j-k次,第i个元素与前i-1个元素不同,把这j-k个第i个元素插入到已有长度k的序列中,就可以转移到dp(i, j)

3. i > j, 不考虑

那么对于2,如何插入?

已有的 k 个元素有 k+1 个位置可以进行插入,问题就是把 j-k 个元素插入到 k+1 个桶中有多少种结果?

表示第 i 个桶,那么问题就等价于的所有非负整数解。

我们把两边同时加上k+1,变成 的所有正整数解。

相当于给j+1个1,插入隔板把它们分到k+1个桶中,每个桶要保证至少有一个元素,所以一共有 j 个可以提供插入隔板的位置,总共有k+1个桶,所以需要在这 j 个空隙中选择出k个位置插入隔板就成k+1个桶。

答案为

最后的2,也就等于 

最后的答案就是dp(m, n)

源码如下:

#include <bits/stdc++.h>
using namespace std; typedef long long int64; const int64 M = 1000000007LL;
const int maxn = 105;
int64 C[maxn][maxn];
int64 dp[maxn][maxn]; void getCombination() {
int n = maxn;
for (int i = 1; i <= n; i++)
C[i][0] = C[i][i] = 1LL; for (int i = 2; i <= n; i++)
for (int j = 1; j <= i; j++)
C[i][j] = (C[i-1][j-1] % M + C[i-1][j] % M) % M;
} int main() { getCombination();
int t, m, n, cas = 1;
scanf("%d", &t);
while ( t-- ) {
scanf("%d%d", &m, &n);
// init
memset(dp, 0LL, sizeof(dp));
for (int i = 1; i <= n; i++) dp[1][i] = 1;
for (int i = 2; i <= n; i++) dp[i][i] = (dp[i-1][i-1] * (int64)i) % M; for (int i = 2; i <= m; i++)
for (int j = i+1; j <= n; j++)
for (int k = i-1; k <= j-1; k++)
dp[i][j] = (dp[i][j] + (C[j][k] * dp[i-1][k]) % M) % M; printf("Case #%d: %lld\n", cas++, dp[m][n]);
}
return 0;
}

思路2:

qqz大神,dp(i, j)表示从 M 个元素中随机选取 i 个不同的元素组成 j 的长度的所有结果

划分子问题

1. i == j, dp(i, i) 随机从 M 个元素选取 i 个元素的全排列,为

2. i == 1, dp(1, j) 表示从 M 个元素中随机选取一个重复 j 次,结果为 M

3. i < j , ,

和的第一部分表示在dp(i-1, j-1)基础上,从剩下的M-i+1个数中取1个放到最后组成dp(i, j). 和的第二部分表示从已经选出的i个元素中挑1个放到最后。

最后的答案就是dp(m, n)

源码如下:

#include <bits/stdc++.h>
using namespace std; using int64 = long long;
const int64 M = 1000000007LL; int64 dp[105][105], A[105][105]; void initA() { for (int i = 1; i <= 100; i++) {
A[i][0] = 1;
for (int j = 1; j <= i; j++)
A[i][j] = ((i-j+1) * A[i][j-1]) % M;
}
} int m, n; int64 f(int i, int j) {
if (dp[i][j] != -1) return dp[i][j];
if (i == j) return dp[i][j] = A[m][i];
else return dp[i][j] = (((m-i+1) * f(i-1, j-1)) % M + (i * f(i, j-1)) % M ) % M;
} int main() {
freopen("A-large-practice.in", "r", stdin);
freopen("a_out.txt", "w", stdout);
int t, cas = 1;
initA();
scanf("%d", &t);
while (t--) {
scanf("%d%d", &m, &n);
for (int i = 1; i <= m; i++)
for (int j = 1; j <= n; j++)
dp[i][j] = -1;
for (int i = 1; i <= n; i++) dp[1][i] = m;
printf("Case #%d: %lld\n", cas++, f(m ,n));
}
return 0;
}

【DP】组合数字的更多相关文章

  1. n全排列输出和 n个数的组合(数字范围a~b)

    n全排列输出: int WPermutation(int num, bool bRepeat) num表示num全排列 bRepeat标志是否产生重复元素的序列. int Permutation(in ...

  2. hdu 4945 2048 (dp+组合的数目)

    2048 Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submi ...

  3. #DP# ----- OpenJudge数字组合

    OpenJudge 2985:数字组合 总时间限制:1000ms  内存限制: 65536kB 描述 有n个正整数,找出其中和为t(t也是正整数)的可能的组合方式.如:n=5,5个数分别为1,2,3, ...

  4. ZOJ-3380 Patchouli’s Spell Cards DP, 组合计数

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3380 题意:有m种不同的元素,每种元素都有n种不同的相位,现在假 ...

  5. 3.29省选模拟赛 除法与取模 dp+组合计数

    LINK:除法与取模 鬼题.不过50分很好写.考虑不带除法的时候 其实是一个dp的组合计数. 考虑带除法的时候需要状压一下除法操作. 因为除法操作是不受x的大小影响的 所以要状压这个除法操作. 直接采 ...

  6. CF 258B Little Elephant and Elections [dp+组合]

    给出1,2,3...m 任取7个互不同样的数a1,a2,a3,a4,a5,a6,a7 一个数的幸运度是数位上4或7的个数 比方244.470幸运度是2. 44434,7276727.4747,7474 ...

  7. bzoj3622已经没有什么好害怕的了 dp+组合+容斥(?)

    3622: 已经没有什么好害怕的了 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1033  Solved: 480[Submit][Status][ ...

  8. 数位dp——奏响数字数位的美妙乐章

    数位dp:处理数字数位关系的一种dp方式. 一般的题目特征十分明显: 1.一般和数字本身有很大关系. 2.一般求数字在区间L,R中的一些信息 3.L,R一般很大,通常能达到long long级别. d ...

  9. HihoCoder 1075 开锁魔法III(概率DP+组合)

    描述 一日,崔克茜来到小马镇表演魔法. 其中有一个节目是开锁咒:舞台上有 n 个盒子,每个盒子中有一把钥匙,对于每个盒子而言有且仅有一把钥匙能打开它.初始时,崔克茜将会随机地选择 k 个盒子用魔法将它 ...

随机推荐

  1. centos 6.5 msyql5.6安装

    MySQL 安装 安装mysql前需要查询系统中含有的有关mysql的软件. rpm -qa | grep -i mysql   如下 代表有mysql ,则先进行卸载 mysql-libs-5.1. ...

  2. ios调用系统相册、相机 显示中文标题、本地化多语言支持

    因为调用系统相册.相机需要显示中文,所以搞了半天才知道是在Project->info->Custom ios Target Properties 添加 Localizations 并加入C ...

  3. C# 解析JSON格式数据

    JSON简介 JSON(全称为JavaScript ObjectNotation) 是一种轻量级的数据交换格式.它是基于JavaScript语法标准的一个子集.JSON采用完全独立于语言的文本格式,可 ...

  4. grunt 基本使用使用(一)。

    使用grunt 之前,需要做一些基本工作. 1.在E盘 新建空文件夹 grunt. 2.在grunt目录下新建package.json 文件,用了存储 npm模块的依赖项.基本依赖块代码如下: { & ...

  5. Sum All Primes

    function sumPrimes(num) { //return num; var arr = []; var ifPrime = function(num){ if(num < 2){ r ...

  6. linux操作系统-memcache安装

    安装配置 1. 安装libevent # tar zxf libevent-1.4.6-stable.tar.gz # cd libevent-1.4.6-stable # ./configure # ...

  7. 关于onmouseover和onmouseout的bug

    总结了一下关于使用onmouseover以及onmouseout会出现的bug 首先简单的布局: <div id="box"> <div>这是一个内容< ...

  8. 分析‖为什么越来越多厂商开始发力VR一体机?

    2015年下半年,国内VR头显市场的主旋律还是PC头显和手机盒子.到了2016年上半年,一体机逐渐上位,成为发布会上的主角. 近期IDEALENS启视在北京召开发布会,发布会的主角K2和K2Pro正是 ...

  9. Yii2 中日志的记录

    Yii2自带日志记录,但用起来感觉比较不是很顺手,故自己封装了个方法,如下: /** * 记录日志 * * @param type $msg * @time 2015年8月31日17:46:20 * ...

  10. 【python】将一个正整数分解质因数

    def reduceNum(n): '''题目:将一个正整数分解质因数.例如:输入90,打印出90=2*3*3*5''' print '{} = '.format(n), : print 'Pleas ...