• HDU 5399 数学 Too Simple


    题意:有m个1~n的映射,而且对于任意的 i 满足 f1(f2(...fm(i))) = i

    其中有些映射是知道的,有些是不知道的,问一共有多少种置换的组合。

    分析:

    首先这些置换一定是1~n的一个置换(也就是1~n的一个排列)才行,因为如果某两个数映射到同一个数的话,那么这个数往后无论怎么映射,这两个数最终映射的结果还是一样的。

    如果所有的f都给出来的话,那么只要判断一下就行。

    如果有一个置换不知道的话,这个置换是可以通过前后的置换计算出来的,所以只有唯一解。

    如果有两个置换不知道的话,第一个置换可以任意确定,有n!种情况,第二个置换根据第一个置换确定。

    以此类推,有c个未知的置换的话,其中c-1个可以自由确定,而且互补影响,最后一个置换根据前面所有置换唯一确定,所以中的方案数是(n!)c-1

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 
     6 typedef long long LL;
     7 
     8 const int maxn = 100 + 10;
     9 const LL MOD = 1000000007;
    10 
    11 int n, m;
    12 bool vis[maxn];
    13 int a[maxn][maxn];
    14 
    15 inline LL mul_mod(LL a, LL b) { return a * b % MOD; }
    16 
    17 LL pow_mod(LL a, int n)
    18 {
    19     LL ans = 1LL, base = a;
    20     while(n)
    21     {
    22         if(n & 1) ans = mul_mod(ans, base);
    23         base = mul_mod(base, base);
    24         n >>= 1;
    25     }
    26     return ans;
    27 }
    28 
    29 LL fac[maxn];
    30 
    31 int main()
    32 {
    33     fac[0] = 1;
    34     for(int i = 1; i < maxn; i++) fac[i] = fac[i - 1] * i % MOD;
    35 
    36     while(scanf("%d%d", &n, &m) == 2 && n)
    37     {
    38         int cnt = 0;
    39         bool ok = true;
    40         for(int i = 1; i <= m; i++)
    41         {
    42             scanf("%d", &a[i][1]);
    43             if(a[i][1] == -1) { cnt++; continue; }
    44             for(int j = 2; j <= n; j++) scanf("%d", &a[i][j]);
    45             memset(vis, false, sizeof(vis));
    46             for(int j = 1; j <= n; j++)
    47             {
    48                 if(vis[a[i][j]]) { ok = false; break; }
    49                 vis[a[i][j]] = true;
    50             }
    51         }
    52         if(!ok) { puts("0"); continue; }
    53 
    54         if(!cnt)
    55         {
    56             bool ok = true;
    57             for(int i = 1; i <= n; i++)
    58             {
    59                 int t = i;
    60                 for(int j = m; j >= 1; j--) t = a[j][t];
    61                 if(t != i) { ok = false; break; }
    62             }
    63             if(ok) puts("1"); else puts("0");
    64         }
    65         else printf("%I64d
    ", pow_mod(fac[n], cnt - 1));
    66     }
    67 
    68     return 0;
    69 }
    代码君
  • 相关阅读:
    CentOS随笔
    CentOS随笔
    CentOS随笔
    CentOS随笔
    产品从生到死的N宗罪
    即将结束的2015。
    Mvvm
    android 热补丁修复框架
    反编译APK
    关于短视频
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4743267.html
Copyright © 2020-2023  润新知