[hdu5399 Too Simple]YY

题意:m个{1,2...n}→{1,2...,n}的函数,有些已知有些未知,求对任意i∈{1,2,...,n},f1(f2(...(fm(i)))=i的方案总数,为了方便简记为F(i)

思路:如果存在一个f,当i!=j时,有f(i)=f(j),那么方案数为0,因为由里到外进行f运算,两个不同的数到这里来了变成了i和j,然后变成了同一个数,最终还是等于同一个数,所以在最外面至少有一个不会满足F(x)=x。如果f全部确定了,那么只需对每个i计算一下F(i)即可确定答案。如果f没确定的个数为cnt,则答案就是n!cnt-1,因为对后(cnt-1)个未确定的f,对于它们的每种合法情况,第一个f有且仅有唯一一种情况使得F(i)=i成立。

 

#pragma comment(linker, "/STACK:10240000")
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define X                   first
#define Y                   second
#define pb                  push_back
#define mp                  make_pair
#define all(a)              (a).begin(), (a).end()
#define fillchar(a, x)      memset(a, x, sizeof(a))
#define copy(a, b)          memcpy(a, b, sizeof(a))

typedef long long ll;
typedef pair<int, int> pii;
typedef unsigned long long ull;

//#ifndef ONLINE_JUDGE
void RI(vector<int>&a,int n){a.resize(n);for(int i=0;i<n;i++)scanf("%d",&a[i]);}
void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>
void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?1:-1;
while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>
void print(const T t){cout<<t<<endl;}template<typename F,typename...R>
void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>
void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}
//#endif
template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);}
template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);}

const double PI = acos(-1.0);
const int INF = 1e9 + 7;
const double EPS = 1e-12;

/* -------------------------------------------------------------------------------- */

const int md = 1e9 + 7;

int n, m, f[101][101], fac[105];

int powermod(int a, int n, int md) {
    int ans = 1, tmp = a;
    while (n) {
        if (n & 1) ans = (ll)ans * tmp % md;
        tmp = (ll)tmp * tmp % md;
        n >>= 1;
    }
    return ans;
}

bool chk() {
    for (int i = 1; i <= n; i ++) {
        int p = i;
        for (int j = m - 1; j >= 0; j --) {
            p = f[j][p];
        }
        if (p != i) return false;
    }
    return true;
}


int main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGE
    fac[0] = 1;
    for (int i = 1; i <= 100; i ++) fac[i] = (ll)fac[i - 1] * i % md;
    int x;
    while (cin >> n >> m) {
        int cnt = 0;
        bool ok = true;
        for (int i = 0; i < m; i ++) {
            scanf("%d", &x);
            if (x == - 1) cnt ++;
            else {
                bool vis[105] = {};
                vis[x] = true;
                f[i][1] = x;
                for (int j = 1; j < n; j ++) {
                    scanf("%d", &x);
                    vis[x] = true;
                    f[i][j + 1] = x;
                }
                for (int i = 1; i <= n; i ++) {
                    if (!vis[i]) ok = false;
                }
            }
        }
        if (!ok) puts("0");
        else {
            if (cnt) printf("%d\n", powermod(fac[n], cnt - 1, md));
            else printf("%d\n", chk());
        }
    }
    return 0;
}
posted @ 2015-08-18 22:52  jklongint  阅读(395)  评论(0编辑  收藏  举报