Codeforces 765D Artsem and Saunders

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;
}

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据