hdu5399(计数)

来源:互联网 发布:叮当软件制作教程 编辑:程序博客网 时间:2024/06/05 06:36

题意:

有n个数字,并给出m个函数变化;

如果给出的函数变化是-1,代表这个函数不确定,可以任意写;

使

f1(f2(......fm(i))) = i;

成立的所有情况有几种;


思路:

现将确定的函数模拟一边;得到的值如果有重复映射,则0种可能,因为一旦又重复映射,我们就不能映射出1到n所有的值;

然后看不确定的函数个数;只需要留一个用来做调整,剩下的都是1到n的全排列;


#include <cstdio>#include <cstring>#define ll long longconst int N = 105;const int MOD = 1e9 + 7;int f[N][N], n, m, tmp[N];ll A[N];void change(int* F) {for (int i = 1; i <= n; i++)tmp[i] = F[tmp[i]];}bool judge(int k) {for (int i = 1; i <= n; i++)tmp[i] = i;for (int i = k - 1; i >= 0; i--)change(f[i]);int vis[N];memset(vis, 0, sizeof(vis));for (int i = 1; i <= n; i++) {if(vis[tmp[i]])return false;vis[tmp[i]] = 1;}return true;}int main() {A[1] = 1;for (int i = 2; i <= N; i++) {A[i] = A[i - 1] * i % MOD;}while (scanf("%d%d", &n, &m) == 2) {memset(f, 0, sizeof(f));int k = 0, c = 0;for (int i = 1; i <= m; i++) {scanf("%d", &f[k][1]);if(f[k][1] == -1) {c++;continue;}for (int j = 2; j <= n; j++) {scanf("%d", &f[k][j]);}k++;}bool ok = judge(k);if (!ok) {printf("0\n");continue;}if (c == 0) {int flag = 0;for (int i = 1; i <= n; i++)if (tmp[i] != i) {flag = 1;break;}if (flag) {printf("0\n");continue;}}ll ans = 1;for (int i = 1; i < c; i++) {ans = ans * A[n] % MOD;}printf("%lld\n", ans); }}



f1(f2(fm(i)))=i







f
1
(f2

0 0