HDU 5399 数学 Too Simple

题意:有m个1~n的映射,而且对于任意的 i 满足 f1(f2(...fm(i))) = i

其中有些映射是知道的,有些是不知道的,问一共有多少种置换的组合。

分析:

首先这些置换一定是1~n的一个置换(也就是1~n的一个排列)才行,因为如果某两个数映射到同一个数的话,那么这个数往后无论怎么映射,这两个数最终映射的结果还是一样的。

如果所有的f都给出来的话,那么只要判断一下就行。

如果有一个置换不知道的话,这个置换是可以通过前后的置换计算出来的,所以只有唯一解。

如果有两个置换不知道的话,第一个置换可以任意确定,有n!种情况,第二个置换根据第一个置换确定。

以此类推,有c个未知的置换的话,其中c-1个可以自由确定,而且互补影响,最后一个置换根据前面所有置换唯一确定,所以中的方案数是(n!)c-1

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5
 6 typedef long long LL;
 7
 8 const int maxn = 100 + 10;
 9 const LL MOD = 1000000007;
10
11 int n, m;
12 bool vis[maxn];
13 int a[maxn][maxn];
14
15 inline LL mul_mod(LL a, LL b) { return a * b % MOD; }
16
17 LL pow_mod(LL a, int n)
18 {
19     LL ans = 1LL, base = a;
20     while(n)
21     {
22         if(n & 1) ans = mul_mod(ans, base);
23         base = mul_mod(base, base);
24         n >>= 1;
25     }
26     return ans;
27 }
28
29 LL fac[maxn];
30
31 int main()
32 {
33     fac[0] = 1;
34     for(int i = 1; i < maxn; i++) fac[i] = fac[i - 1] * i % MOD;
35
36     while(scanf("%d%d", &n, &m) == 2 && n)
37     {
38         int cnt = 0;
39         bool ok = true;
40         for(int i = 1; i <= m; i++)
41         {
42             scanf("%d", &a[i][1]);
43             if(a[i][1] == -1) { cnt++; continue; }
44             for(int j = 2; j <= n; j++) scanf("%d", &a[i][j]);
45             memset(vis, false, sizeof(vis));
46             for(int j = 1; j <= n; j++)
47             {
48                 if(vis[a[i][j]]) { ok = false; break; }
49                 vis[a[i][j]] = true;
50             }
51         }
52         if(!ok) { puts("0"); continue; }
53
54         if(!cnt)
55         {
56             bool ok = true;
57             for(int i = 1; i <= n; i++)
58             {
59                 int t = i;
60                 for(int j = m; j >= 1; j--) t = a[j][t];
61                 if(t != i) { ok = false; break; }
62             }
63             if(ok) puts("1"); else puts("0");
64         }
65         else printf("%I64d\n", pow_mod(fac[n], cnt - 1));
66     }
67
68     return 0;
69 }

代码君

时间: 2024-11-14 22:02:35

HDU 5399 数学 Too Simple的相关文章

hdu 5399(数学推理)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5399: 题意: 给你m个函数f1,f2,?,fm:{1,2,?,n}→{1,2,?,n}(即所有的x∈{1,2,?,n},对应的f(x)∈{1,2,?,n}),已知其中一部分函数的函数值,问你有多少种不同的组合使得所有的i(1≤i≤n),满足f1(f2(?fm(i)))=i 对于函数集f1,f2,?,fm and g1,g2,?,gm,当且仅当存在一个i(1≤i≤m),j(1≤j≤n),fi(j)≠

【HDU 5399】Too Simple

题 Description Rhason Cheung had a simple problem, and asked Teacher Mai for help. But Teacher Mai thought this problem was too simple, sometimes naive. So she ask you for help. Teacher Mai has m functions f1,f2,...,fm:{1,2,...,n}→{1,2,...,n}(that mea

hdu 5349 MZL&#39;s simple problem

Problem Description A simple problem Problem Description You have a multiple set,and now there are three kinds of operations: 1 x : add number x to set 2 : delete the minimum number (if the set is empty now,then ignore it) 3 : query the maximum numbe

【multiset】hdu 5349 MZL&#39;s simple problem

[multiset]hdu 5349 MZL's simple problem 题目链接:hdu 5349 MZL's simple problem 题目大意 n次操作,插入元素.删除最小元素.查询最大元素并输出. C++STL的multiset的使用 set--多元集合(元素不可重复),multiset--可重复元素的多元集合 多元集合(MultiSets)和集合(Sets)相像,只不过支持重复对象.(具体用法请参照set容器) set和multiset内部是以平衡二叉树实现的: 从内部数据结

hdu 5349 MZL&#39;s simple problem(multiset)

代码: #include<set> #include<cstdio> using namespace std; multiset<int> st; int main() { int n; multiset<int>::iterator it; while(scanf("%d",&n)==1) { st.clear(); int k,num; for(int i=0; i<n; i++) { scanf("%d&qu

hdu 4961 数学杂题

http://acm.hdu.edu.cn/showproblem.php?pid=4961 先贴个O(nsqrtn)求1-n所有数的所有约数的代码: vector<int>divs[MAXN]; void caldivs() { for(int i=1;i<MAXN;i++) for(int j=i;j<MAXN;j+=i) divs[j].push_back(i); } 有了这个当时理下思路就可写了,但是重复数处理注意: 1.用一个数组vis[]  vis[i]=1表示i存在

【HDOJ 5399】Too Simple

[HDOJ 5399]Too Simple 函数映射问题 给出m函数 里面有0~m个函数未知(-1) 问要求最后1~n分别对应仍映射1~n 有几种函数写法(已给定的函数不可变 只可更改未知的函数的映射) 如果映射过程中出现多对一 即入度n出度小于n 的函数 必定冲突 即最后必有落单 映射失败 为0 如果映射完整 已知的连续函数可压缩成一个函数 中间出入度可忽略 因此可压缩为-1 f -1 -1 f -1 -1 f这种形态 进一步深入可发现中间的f仅仅起到通道作用 即可压缩为连续的-1之间的映射

hdu - 5349 MZL&#39;s simple problem(解题报告)

A - MZL's simple problem Time Limit:1500MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Description A simple problem Problem Description You have a multiple set,and now there are three kinds of operations: 1 x : add number

HDU 5349 MZL&#39;s simple problem(优先队列)

MZL's simple problem Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 776    Accepted Submission(s): 375 Problem Description A simple problem Problem Description You have a multiple set,and now