多校第九場Too Simple題解

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=5399

題意:給你m個映射,每個自變量x,對應一個f(x),這m個映射中有某一些已知的,給出你從1到n對應的映射值,剩下的一些不知道映射關係的,給你-1,要求找出符合條件的映射組合有多少組,其中要求是:對於i從1到n都滿足f1(f2(……fm(i)))=i

思路:開個腦洞發現:如果-1的個數不止一個,那麼只有最後一個-1所對應的映射是確定的,其他的都是任意的,如果-1的個數,只有一個,那麼結果就是1,如果沒有-1,那麼還需要判斷本身這個映射是不是滿足條件。在做這些之前還需要考慮,這個映射是不是一一對應的,也就是這個映射是不是一個函數,只有這樣才能繼續討論-1個數的問題,如果不是一一對應的,那麼不同的i對應同樣的f(i)就回不到i。

官方解釋來一個幫助理解:首先要求每個f(i)是個排列,否則如果某個f(i)​將兩個數映射向同一個數,那麼最後這兩個數得到的值一定相同。如果還剩一個位置爲-1,那麼這個排列是唯一確定的,假設,那麼所以假設有c(c≥1)個-1,那麼答案爲(n!)^{c-1} 個可行的方案。

注意特判所有函數都已知的情況。

代碼:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <cctype>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <sstream>
#include <fstream>
#define debug "output for debug\n"
#define pi (acos(-1.0))
#define eps (1e-8)
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
const int maxn = 100005;
int n, m;
int b[105][105];
const ll mod = 1e9 + 7;
ll a[105];
int check()
{
    int a[105];
    int f[105];
    for(int i=1;i<=n;i++)
        a[i]=i;
    for(int i=m; i>=1; i--)
    {
        for(int j=1; j<=n; j++)
            f[j]=b[i][a[j]];
        for(int j=1; j<=n; j++)
            a[j]=f[j];
    }
    for(int i=1;i<=n;i++)
    if(a[i]!=i)
      return 0;
    return 1;
}
int main () {
    a[0] = 1;
    for (int i = 1; i <= 100; i++)
        a[i] = i * a[i - 1] % mod;
    while(scanf("%d%d", &n, &m)!=EOF)
     {
        int k = 0;
       int flag = 0;
        for (int i = 1; i <= m; i++)
            {
            int sum[111] = {0};
            scanf("%d", &b[i][1]);
            if (b[i][1] == -1) {
                k++;
                continue;
            }
            sum[b[i][1]]++;
            for (int j = 2; j <= n; j++)
             {
                scanf("%d", &b[i][j]);
                sum[b[i][j]]++;
                if (sum[b[i][j]] > 1) flag = 1;
            }
        }
        if (flag) {
            printf("0\n");
            continue;
        }
        if (k == 0) {
            printf("%d\n", check());
            continue;
        }
        ll ans = 1;
        k--;
        while(k--) {
            ans = ans * a[n];
            ans %= mod;
        }
        printf("%I64d\n", ans);
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章