2017 Multi-University Training Contest - Team 1 1006 Function
2017-07-26 21:28
393 查看
题目链接:VJ:https://vjudge.net/problem/HDU-6038 HDU链接:http://acm.hdu.edu.cn/contests/contest_showproblem.php?cid=759&pid=1006
题目大意, 给定两个排列a b 长度分别为n(0~n-1), m(0~m-1) 定义F(i)=bF(ai), 问有多少种方案使得每一个F(i)都合法, 方案数%1e9 + 7
思路: 对于一个排列来说, a[i]表示的是一个位置 a[a[i]] 又指向一个位置, 肯定是一个或多个环。
大佬的博客里写道:
比如说:如果 a 序列是 2 0 1 那么我们可以发现
f(0) = b[f(a[0])] = b[f(2)]
f[1] = b[f(a[1])] = b[f(0)]
f[2] = b[f(a[2])] = b[f(1)]
那么f(0) f(1) f(2) 也是循环的
所以说, 只要找出A中所有的环,B中所有的环, 如果A的环长度为B的倍数, 则为合法, 方案数加上当前B环的长度
题目大意, 给定两个排列a b 长度分别为n(0~n-1), m(0~m-1) 定义F(i)=bF(ai), 问有多少种方案使得每一个F(i)都合法, 方案数%1e9 + 7
思路: 对于一个排列来说, a[i]表示的是一个位置 a[a[i]] 又指向一个位置, 肯定是一个或多个环。
大佬的博客里写道:
比如说:如果 a 序列是 2 0 1 那么我们可以发现
f(0) = b[f(a[0])] = b[f(2)]
f[1] = b[f(a[1])] = b[f(0)]
f[2] = b[f(a[2])] = b[f(1)]
那么f(0) f(1) f(2) 也是循环的
所以说, 只要找出A中所有的环,B中所有的环, 如果A的环长度为B的倍数, 则为合法, 方案数加上当前B环的长度
#include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<algorithm> #include<queue> using namespace std; typedef long long LL; const int MaxN = 1e5; const int pt = 1e9 + 7; int a[MaxN + 5], b[MaxN + 5]; int father[MaxN + 5]; int len_a[MaxN + 5], len_b[MaxN + 5]; int cnt[MaxN + 5], ans[MaxN + 5]; int n, m, Case; int find(int a){ if(father[a] == a) return a; else return father[a] = find(father[a]); } void Union(int a, int b){ int fa = find(a), fb = find(b); if(fa != fb) father[fa] = fb; } int main(){ while(~scanf("%d %d", &n, &m)){ memset(len_a, 0, sizeof(len_a)); memset(len_b, 0, sizeof(len_b)); memset(cnt, 0, sizeof(cnt)); memset(ans, 0, sizeof(ans)); for(int i = 0; i < n; i++) father[i] = i; for(int i = 0; i < n; i++){ scanf("%d", &a[i]); Union(i, a[i]); } for(int i = 0; i < n; i++) len_a[find(i)]++; for(int i = 0; i < m; i++) father[i] = i; for(int i = 0; i < m; i++){ scanf("%d", &b[i]); Union(i, b[i]); } for(int i = 0; i < m; i++) len_b[find(i)]++; for(int i = 0; i < m; i++) cnt[len_b[i]]++; for(int i = 1; i <= m; i++) for(int j = i; j <= n; j+= i) ans[j] += 1LL * cnt[i] * i; LL tot = 1; for(int i = 0; i < n; i++) if(len_a[i] > 0) tot = (tot * ans[len_a[i]]) % pt; printf("Case #%d: %lld\n", ++Case, tot % pt); } return 0; }
相关文章推荐
- 2017 Multi-University Training Contest - Team 1 1006&&HDU 6038 Function【DFS+数论】
- 2017 Multi-University Training Contest - Team 1--1006 Function
- 2017 Multi-University Training Contest - Team 1 1006 Function(置换群)
- 2017 Multi-University Training Contest - Team 1 1006 Function(思维 循环节)
- 2017 Multi-University Training Contest - Team 1 1006 Function
- 2017 Multi-University Training Contest - Team 2 :1006 Funny Function(找规律+逆元+快速幂取模)
- 2017 Multi-University Training Contest - Team 5 1006 Rikka with Graph
- 2017 Multi-University Training Contest - Team 5:1006&hdu6090、 Rikka with Graph
- 2017 Multi-University Training Contest - Team 1(hdu 6038 Function)
- HDU 6050 Funny Function(构造矩阵+推公式)——2017 Multi-University Training Contest - Team 2
- 2017 Multi-University Training Contest - Team 1 1006 【思维+强联通找环】
- hdoj 6050(2017 Multi-University Training Contest - Team 2) Funny Function
- HDU 6038 Function(找规律)——2017 Multi-University Training Contest - Team 1
- 2017 Multi-University Training Contest - Team 2 1006
- 2017 Multi-University Training Contest - Team 1 :Function
- HDU-6038 Function - 2017 Multi-University Training Contest - Team 1(构造置换或强连通分量)
- 2017 Multi-University Training Contest - Team 1 - 1006
- 2017 Multi-University Training Contest - Team 2 - 1006
- 2017 Multi-University Training Contest - Team 1 Function
- 2017 Multi-University Training Contest - Team 6 【solved:5 / 12】