zoukankan      html  css  js  c++  java
  • [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 }
  • 相关阅读:
    补 七月九日学习报告
    七月八日学习报告
    学习笔记164—层次聚类 Hierarchical Clustering
    学习笔记163—理解模型正则化:L1正则、L2正则(理论+代码)
    学习笔记162—Linear Regression vs Logistic Regression
    学习笔记161—win7C盘 虚拟内存移动到D盘或其他盘符
    学习笔记160—文献引文分析利器 HistCite 详细使用教程
    学习笔记159—电脑word文档回车表格随文字移动
    学习笔记158—INTRODUCTION TO LINEAR MIXED MODELS
    学习笔记157—Nipype的安装
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/7656237.html
Copyright © 2011-2022 走看看