hdu 5399 Too Simple

来源:互联网 发布:php curl 异常处理 编辑:程序博客网 时间:2024/06/05 06:46

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=5399

解题思路:

题目大意:

给m个函数,其对应是自变量x属于{1,2,...n},f(x)属于{1,2...n},给出其中一些函数,问有多少种不同的函数集合,使得1<=i<=n,f1(f2(f3...fm(i))) = i。

解释样例:

3 3

1 2 3

-1

3 2 1

样例写成函数的形式就是

n=3,m=3(m行,每行n个数)

f1(1)=1,f1(2)=2,f1(3)=3

f2(1)、f2(2)、f2(3)的值均未知

f3(1)=3,f3(2)=2,f3(3)=1

所以要使所有的i(1≤i≤n),满足f1(f2(⋯fm(i)))=i,只有一种组合情况,即f2(1)=3,f2(2)=2,f2(3)=1

官方题解:

首先要求每个f_ifi是个排列,否则如果某个f_ifi将两个数映射向同一个数,那么最后这两个数得到的值一定相同。

如果还剩一个位置为-11,那么这个排列是唯一确定的,假设X*f_i*Y=IXfiY=I,那么f_i=X^{-1}*Y^{-1}fi=X1Y1.

所以假设有c(c\geq 1)c(c1)-11,那么答案为(n!)^{c-1}(n!)c1个可行的方案。

算法思想:

当某一行的映射不能保证一对一时(换句话说就是多对一),那么一定存在i(1≤i≤n)不满足f1(f2(⋯fm(i)))=i,此时结果为0。除了这种特殊情况,最后的解只跟-1的个数有关,当-1的个数是0时,结果未必是0,,要判断对所有的i是否都满足条件,如果满足,结果是1,否则结果是0。当只有一个-1的时候,因为对应关系都已经确定了,所以只有1种可行解,而当有两个-1时,其中一个函数的值可以根据另一个函数的改变而确定下来,故有n!种解。依此类推,当有k个-1时,解为(n!)^(k-1)(k>0)。


AC代码:

#include <iostream>  #include <cstdio>  #define MOD 1000000007  using namespace std;  typedef long long ll;  int n,m;  ll f[105],a[105][105];    int main(){      f[0] = 1;      for(int i = 1; i <= 100; i++)          f[i] = f[i-1]*i%MOD;      while(~scanf("%d%d",&n,&m)){          ll tot = 0,ans = 1;          for(int i = 1; i <= m; i++){              scanf("%lld",&a[i][1]);              if(a[i][1] == -1)                  tot++;              else{                  for(int j = 2; j <= n; j++){                      scanf("%lld",&a[i][j]);                      for(int k = j-1; k >= 1; k--)                          if(a[i][j] == a[i][k])                              ans = 0;                  }              }          }          for(int i = 1; i < tot; i++)              ans = ans*f[n]%MOD;          if(tot == 0){              for(int i = 1; i <= n; i++)                  a[0][i] = i;              for(int i = m; i>= 1; i--)                  for(int j = 1; j <= n; j++)                      a[0][j] = a[i][a[0][j]];//映射转换            for(int i = 1; i <= n; i++)                  if(a[0][i] != i)                      ans = 0;//如果不能变回原来的数列,则为0        }          printf("%lld\n",ans);      }      return 0;  }  




0 0
原创粉丝点击