链接:
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 the number of arrangement of first N natural numbers, where in first M positions; exactly K numbers are in their initial position.
- For Example, N = 5, M = 3, K = 2
- You should count this arrangement {
- 1, 4, 3, 2, 5
- }, here in first 3 positions 1 is in 1st position and 3 in 3rd position. So exactly 2 of its first 3 are in there initial position.
But you should not count {1, 2, 3, 4, 5}.
思路:
错排:
F[n] = (n-1)*(F[n-1]+F[n-2]),F[i] 为长度 i 的错排种类.
递推:
第一步, 首元素插到剩下 n-1 个元素位置 k.
第二步, 可以选择将 k 插到首位置, 此时就剩下 n-2 个, 即 F[n-2]
可以不插到首位置, 将原本 k 位置元素删除, k 插到首元素位置, 看成 k 位置, 则为 F[n-1]
代码:
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #include<string>
- #include<algorithm>
- #include<math.h>
- #include<vector>
- #include<map>
- #include<set>
- #include<utility>
- using namespace std;
- typedef long long LL;
- const int INF = 1e9;
- const int MAXN = 1e3+10;
- const int MOD = 1e9+7;
- int n, k, m;
- LL P[MAXN], F[MAXN];
- LL PowMod(LL a, LL b)
- {
- LL res = 1;
- while(b)
- {
- if (b&1)
- res = (1LL*res*a)%MOD;
- a = (1LL*a*a)%MOD;
- b>>= 1;
- }
- return res;
- }
- LL Com(LL a, LL b)
- {
- if (b == 0 || a == b)
- return 1;
- return 1LL*P[a]*PowMod(P[b]*P[a-b]%MOD, MOD-2)%MOD;
- }
- void Init()
- {
- P[1] = 1;
- for (int i = 2;i < MAXN;i++)
- P[i] = 1LL*i*P[i-1]%MOD;
- F[1] = 0, F[0] = F[2] = 1;
- for (int i = 3;i < MAXN;i++)
- F[i] = 1LL*(i-1)*((F[i-1]+F[i-2])%MOD)%MOD;
- }
- int main()
- {
- Init();
- int cnt = 0;
- int t;
- scanf("%d", &t);
- while(t--)
- {
- printf("Case %d:", ++cnt);
- scanf("%d%d%d", &n, &m, &k);
- LL res = 0LL;
- for (int i = 0;i <= n-m;i++)
- res = ((res + 1LL*Com(n-m, i)*F[n-k-i]%MOD)%MOD+MOD)%MOD;
- res = 1LL*res*Com(m, k)%MOD;
- printf("%lld\n", res);
- }
- return 0;
- }
来源: http://www.bubuko.com/infodetail-3294292.html