Light oj 1095 - Arrange the Numbers (组合数学+递推)

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1095

题意:

给你包含1~n的排列,初始位置1,2,3...,n,问你刚好固定前m个数中的k个数的位置,问你有多少中排列方案。(比如5 3 2有1 4 3 2 5这种方案,1和3固定了)

思路:

前m个取k个就是C(m, k)个方案。然后就是类似错排的思想,设dp[i]为i个数在初始位置各不相同。其中的组合数用逆元算出。

ans = dp[m - k] * C(n - m, 0) + dp[m - k + 1] * C(n - m, 1) .. dp[n - k] * C(n - m, n - m),这个式子表示取后面n-m个数的某些数 与 前面的m - k个数形成错排,剩下的数位置不变。

最后就是ans * C(m, k)

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 LL mod = 1e9 + 7, dp[1005];
 5 LL f[1005];
 6 LL fpow(LL a, LL n) {
 7     LL ans = 1;
 8     while(n) {
 9         if(n & 1)
10             ans = ans * a % mod;
11         a = a * a % mod;
12         n >>= 1;
13     }
14     return ans;
15 }
16 int main()
17 {
18     dp[0] = 1;
19     dp[1] = 0, dp[2] = 1;
20     f[1] = f[0] = 1, f[2] = 2;
21     for(LL i = 3; i <= 1000; ++i) {
22         dp[i] = (dp[i - 1] + dp[i - 2]) % mod * (LL)(i - 1) % mod;
23         f[i] = f[i - 1] * (LL)i % mod;
24     }
25     int n, m, k, t;
26     scanf("%d", &t);
27     for(int ca = 1; ca <= t; ++ca) {
28         scanf("%d %d %d", &n, &m, &k);
29         if(n == m && m - k == 1) {
30             printf("Case %d: 0\n", ca);
31             continue;
32         }
33         LL ans = f[m] * fpow(f[k]*f[m - k]%mod, mod - 2) % mod;
34         int temp = m - k, temp2 = n - m;
35         LL res = 0;
36         for(int i = temp; i <= temp2 + temp; ++i) {
37             res = (res + dp[i] * f[temp2] % mod * fpow(f[i - temp]*f[temp2 - i + temp] % mod, mod - 2) % mod) % mod;
38         }
39         printf("Case %d: %lld\n", ca, ans * res % mod);
40     }
41     return 0;
42 }
时间: 2024-10-21 01:07:57

Light oj 1095 - Arrange the Numbers (组合数学+递推)的相关文章

Light OJ 1095 Arrange the Numbers

给定n,m,k,要求在n的全排列中,前m个数字中恰好有k个位置不变,有几种方案?首先,前m个中k个不变,那就是C(m,k),然后利用容斥原理可得 ans=ΣC(m,k)*(-1)^i*C(m-k,i)*(n-k-i)! (0<=i<=m-k) 1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream&g

LightOJ - 1095 - Arrange the Numbers(错排)

链接: https://vjudge.net/problem/LightOJ-1095 题意: Consider this sequence {1, 2, 3 ... N}, as an initial sequence of first N natural numbers. You can rearrange this sequence in many ways. There will be a total of N! arrangements. You have to calculate t

UVA 11481 Arrange the Numbers(组合数学 错位排序)

题意:长度为n的序列,前m位恰好k位正确排序,求方法数 前m位选k个数正确排,为cm[m][k],剩余m - k个空位,要错排,这m - k个数可能是前m个数中剩下的,也可能来自后面的n - m个数 考虑这样一个问题,共n个数,前i位错排的方法数,显然dp[i][0] = i! 递推考虑:处理到第i个数时,等价于前i - 1个数错排的方法数减去在前i - 1个数错排的情况下第i位恰好为i的方法数,后者相当于n - 1个数前i - 1位错排 所以 dp[n][i] = dp[n][i - 1] -

51NOD 1639 绑鞋带(组合数学 + 递推)

传送门 有n根鞋带混在一起,现在重复n次以下操作:随机抽出两个鞋带头,把它们绑在一起.可以想象,这n次之后將不再有单独的鞋带头,n条鞋带系成了一些环.那么有多大概率刚好所有这些鞋带只形成了一个环? Input 仅一行,包含一个整数n (2<=n<=1000). Output 输出一行,为刚好成环的概率. Input示例 2 Output示例 0.666667 解题思路: 考虑n根鞋带时第一个操作,只要不选到同一根鞋带,就等价变成n-1根时的情形.这样我们就可以递推了,现在假设已经有 i-1 根

light oj 1095 组合数学

1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #include <math.h> 5 #include <iostream> 6 #include <algorithm> 7 #include <climits> 8 #include <queue> 9 #define ll long long 10 11 using na

lightoj 1095 - Arrange the Numbers(dp+组合数)

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1095 题解:其实是一道简单的组合数只要推导一下错排就行了.在这里就推导一下错排 dp[i]=(i-1)*dp[i-2](表示新加的那个数放到i-1中的某一个位置然后那个被放位置的数放在i这个位置就是i-2的错排)+(i-1)*dp[i-1](表示新加的那个数放到i-1中的某一个位置然后用那个位置被占的数代替i这个位置的数就是i-1的错排) #include <iostream

Light OJ 1095

题意: 给你 N 个数, 总共有 N! 种排列, 现在 要你统计前 M 个数 刚好 有K 个数 在原来的位置上 的排列个数 思路: 首先 M 中选 K C(m,k): 则 共 剩下 n - k 个数, 而 n-m 个数中可以允许有数在原来的位置: 故 枚举 n-m 中有多少个数 在原来的位置上, 剩下的 n - k - i 个数 就是一个错排列了 (错排列 : D[i] = (i-1) * (D[i-1] + D[i-2] ) ; ) #include<bits/stdc++.h> using

lightoj 1095 - Arrange the Numbers (错排数)

题意: 求n个数的排列,前m个中有k个在自己的位置上的方法数. 思路: 设D[n]为n个元素的错排数. 于是我们有D[1] = 0 D[2] = 1: D[n] = (D[n-1] + D[n-2]) * (i-1) 考虑问题本身,我们首先从前m个数选k个数不动.即C(m,k).对于没有选的前m中的m-k个数肯定是参与了错排,而后面n-m个数中参加错排的个数不定,所以我们枚举一个后面n-m个数中选出i(0 <= i <= n - m)个数有没有参与错排.总共就有n-k-i参与了错排. 综上所述

Timus Online Judge1009---K-based Numbers(简单递推dp)

Let's consider K-based numbers, containing exactly N digits. We define a number to be valid if its K-based notation doesn't contain two successive zeros. For example: 1010230 is a valid 7-digit number; 1000198 is not a valid number; 0001235 is not a