Codeforces 765D Artsem and Saunders
题目链接
http://codeforces.com/problemset/problem/765/D
题目大意
给你一个函数 $f(x)$ ,让你求出两个函数 $g(x)$ 和 $h(x)$ 使得 $g(h(x)) = x$ 和 $h(g(x)) = f(x)$ 成立,对于 $f(x)$ 和 $g(x)$ , $x$ 的定义域为 $1$ 到 $n$ ,对于 $h(x)$ 定义域为 $1$ 到 $m$
你需要求出全部的 $g(x)$ 和 $h(x)$ 以及 $m$ ,无解输出 $-1$
题目分析
可观察得到三个式子
$$g(h(g(x))) = g(x) = g(f(x))$$
$$h(g(h(x))) = f(h(x)) = h(x)$$
$$h(g(h(g(x)))) = f(x) = f(f(x))$$
所以由第三个式子可知必有 $f(x) = f(f(x))$ 时才有解
由第二个式子可知 $h(x)$ 里的元素是 $x = f(x)$ 构成的
$m$ 就是 $x=f(x)$ 的个数
在通过第一个式子确定 $g(x)$ 的值
代码
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <string> #include <algorithm> #include <queue> using namespace std; queue <int> q; int n, m; int f[100005]; int g[100005]; int h[100005]; int main(){ int i, j; bool flag = true; cin >> n; for(i=1;i<=n;i++){ cin >> f[i]; if(i == f[i]){ q.push(i); } } for(i=1;i<=n;i++){ if(f[i] != f[f[i]]){ flag = false; } } m = 0; while(!q.empty()){ m++; h[m] = q.front(); g[h[m]] = m; q.pop(); } for(i=1;i<=n;i++){ g[i] = g[f[i]]; } if(!flag){ cout << -1 << endl; }else{ cout << m << endl; for(i=1;i<n;i++){ cout << g[i] << " "; } cout << g[n] << endl; for(i=1;i<m;i++){ cout << h[i] << " "; } cout << h[m] << endl; } return 0; }