[Luogu 2817]宋荣子的城堡

Description

saruka有一座大大的城堡!城堡里面有n个房间,每个房间上面都写着一个数字p[i]。有一天,saruka邀请他的小伙伴LYL和 MagHSK来城堡里玩耍(为什么没有妹子),他们约定,如果某一个人当前站在i号房间里,那么下一步他就要去p[i]号房间,在下一步就要去 p[p[i]]号房间。

为了增加趣味性,saruka决定重新书写一下每个房间的p[i],以满足:

<1>如果从编号为1-k的某个房间走,按照规则走,必须能走回1号房间。特别的,如果从1号房间开始走,也要走回1号房间。(至少走一步,如果p[1] = 1,从1走到1也算合法)

<2>如果从编号大于k的房间开始,按照规则走,一定不能走到1号房间。

saruka想知道,一共有多少书写p[i]的方案可以满足要求?

Input

共一行两个数字n,k,含义如题。

Output

一个数字,表示合法的方案数。答案对10 ^ 9 + 7取模。

Sample Input

5 2
7 4

Sample Output

54
1728

Hint

1 <= n <= 10 ^ 18

1 <= k <= min(8,n)

题解

很显然这道题我们要分治考虑,即分为$[1,k]$和$[k+1,n]$两个区间的点来计算。

首先我们很容易的知道后面这个区间的个数是${(n-k)}^{n-k}$,因为后面的点不能与$[1,k]$的点连,并且可以随便连,不用管是否连通。

那么我们现在考虑前面的$k$个点。我们想:首先这个图是一个典型的基环内向树,既然所有的点都能到达$1$号点,那么这个$1$号点肯定在基环上,并且整个图都是连通的。

我们来考虑这个问题:怎样构成这个图呢?

我们先假设只有$n-1$条边,那么使图要连通的话,显然构成了一棵树且根节点为$1$;因为边是有向的,显然所有边的方向是从儿子节点到父节点。

现在我们加上忽略的这条边,显然我从$1$号根节点连向任意一个节点都是可以的(包括根节点)。

我们拓展到一般的情况如果$1$号点不一定是根节点:那么我们只要把根节点连向$1$号点的位置就可以了。

我们得出这样一个结论:只要构成了一棵树,我都有方法使它满足条件,并且无论根节点是什么。并且我们能够得到,一个无向树确定了根节点,我都有办法确定方向使它们指向根。

带编号的点的无根生成树我们想到了$Cayley$公式,不知道的可以戳我之前写的一篇博客:->戳我<-

我们可以得到$n^{n-2}$棵无根树,并且我所有的点都可以确立为根,那么在每种形态下,我又有了$n$个版本。

那么前一部分的方案数就是$k^{k-1}$。

根据乘法原理:最终答案就是$k^{k-1}*{(n-k)}^{n-k}$。

 1 //It is made by Awson on 2017.10.12
 2 #include <set>
 3 #include <map>
 4 #include <cmath>
 5 #include <ctime>
 6 #include <cmath>
 7 #include <stack>
 8 #include <queue>
 9 #include <vector>
10 #include <string>
11 #include <cstdio>
12 #include <cstdlib>
13 #include <cstring>
14 #include <iostream>
15 #include <algorithm>
16 #define LL long long
17 #define Min(a, b) ((a) < (b) ? (a) : (b))
18 #define Max(a, b) ((a) > (b) ? (a) : (b))
19 #define sqr(x) ((x)*(x))
20 using namespace std;
21 const LL MOD = 1e9+7;
22 
23 LL n, k;
24 
25 LL quick_pow(LL a, LL b) {
26   LL sum = 1;
27   a %= MOD;
28   while (b) {
29     if (b&1) sum = sum*a%MOD;
30     b >>= 1;
31     a = a*a%MOD;
32   }
33   return sum;
34 } 
35 void work() {
36   scanf("%lld%lld", &n, &k);
37   LL ans1 = quick_pow(k, k-1);
38   LL ans2 = quick_pow(n-k, n-k);
39   printf("%lld
", ans1*ans2%MOD);
40 }
41 int main() {
42   work();
43   return 0;
44 }
原文地址:https://www.cnblogs.com/NaVi-Awson/p/7656237.html