标签:机智题
题目链接: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;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:机智题
原文地址:http://blog.csdn.net/li1004133206/article/details/47781901