4517: [Sdoi2016]排列计数

链接

思路:

  首先,要确定定m个位置,这些位置要求必须i=a[i],所以方案数是C(n,m),对于剩下的位置,要求i!=a[i],所以要求是一个错排。

错排公式

p[0] = 0,p[1] = 1

p[i] = (i-1)*(p[i-1]+p[i-2])

代码

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<iostream>
 6 
 7 using namespace std;
 8 
 9 const int mod = 1e9+7;
10 
11 int f[1000100],p[1000100];
12 
13 inline int read() {
14     int x = 0,f = 1;char ch=getchar();
15     for (; ch<'0'||ch>'9'; ch=getchar()) if(ch=='-')f=-1;
16     for (; ch>='0'&&ch<='9'; ch=getchar()) x=x*10+ch-'0';
17     return x*f;
18 }
19 
20 void init() {
21     f[0] = 1;
22     for (int i=1; i<=1000000; ++i) f[i] = (1ll * f[i-1] * i) % mod;
23     p[1] = 0;p[2] = 1;
24     for (int i=3; i<=1000000; ++i) p[i] = (1ll * (i-1) * (p[i-1] + p[i-2])) % mod;
25 }
26 
27 int inv(int a,int b) {
28     int ans = 1;
29     while (b) {
30         if (b & 1) ans = (1ll*ans*a) % mod;
31         a = (1ll * a * a) % mod;
32         b >>= 1;
33     }
34     return ans % mod;
35 }
36 
37 void solve(int n,int m) {
38     if (n == m) {cout << "1
";return ;}
39     int t1 = inv(f[m],mod-2),t2 = inv(f[n-m],mod-2);
40     int ans = (1ll * f[n] * t1) % mod;
41     ans = (1ll * ans * t2) % mod;
42     ans = (1ll * ans * p[n-m]) % mod;
43     cout << ans << "
";
44 }
45 
46 int main() {
47     int T = read();
48     init();
49     while (T--) {
50         int n = read(),m = read();
51         solve(n,m);
52     }
53     return 0;
54 }
原文地址:https://www.cnblogs.com/mjtcn/p/8709801.html