• D. Infinite Path (dfs、思维)


    题目:传送门

    题意

    给你一个长度为 n 的排列 p,和一个长度为 n 的颜色数组 c,无限路径的定义为 i, p[i], p[p[i]], p[p[p[i]]],且 c[i] = c[p[i]] = c[p[p[i]]] = .........;排列 a 和排列 b 相乘得到的排序 c,满足 c[i]  = b[a[i]],排列 p 的 k 次方,p^k = p * p * p * p (k 个 p),问你最小的非0 k 是多少,使得 p^k 存在一个 i 满足无限路径。

    思路

    无限路径,必然是一个循环,我们将给定的排列 p 转为有向图,那么得到的图由许多互不相交的环构成,我们对 i 和 p[i] 连一条有向边,通过 dfs 找到所有的环。

    假设现在有一个长度为 tot 的环 tmp,对于第一个元素 tmp[1],若 p 变成了 p^k,那么这个环又会分为许多环,例如 k = 2 的时候, tmp[1] = tmp[tmp[1]],相当于一次跳了两步,那么如果 tot % 2 == 0, 那么,这个长度为 tot 的环就又会分为两个长度为 tot / 2 的环。所以,我们枚举 tot 的因子,然后判断一下,将环分为许多子环之后,是否存在 i 满足无限路径,维护一个最小的答案,就行啦。

    #include <bits/stdc++.h>
    #define LL long long
    #define ULL unsigned long long
    #define mem(i, j) memset(i, j, sizeof(i))
    #define rep(i, j, k) for(int i = j; i <= k; i++)
    #define dep(i, j, k) for(int i = k; i >= j; i--)
    #define pb push_back
    #define make make_pair
    #define INF INT_MAX
    #define inf LLONG_MAX
    #define PI acos(-1)
    #define fir first
    #define sec second
    using namespace std;
    
    const int N = 1e6 + 5;
    
    const LL mod = 998244353;
    
    LL ksm(LL a, LL b) { LL ans = 1LL; while(b) { if(b & 1) ans = ans * a % mod; a = a * a % mod; b >>= 1; }  return ans; }
    
    int a[N], c[N], tmp[N], ans, tot;
    
    bool vis[N];
    
    bool judge(int x, int y) {
        for(int i = 1; i <= x; i++) {
            int t = i; bool flag = 0;
            for(int j = 1; j <= y; j++) {
                if(c[tmp[t]] != c[tmp[i]]) {
                    flag = 1; break;
                }
                t = (t + x - 1) % tot + 1;
            }
            if(!flag) return 1;
        }
        return 0;
    }
    
    void dfs(int x) {
        tot = 0;
    
        tmp[++tot] = x; vis[x] = 1;
    
        for(int i = a[x]; i != x; i = a[i]) tmp[++tot] = i, vis[i] = 1;
    
        for(int i = 1; i * i <= tot; i++) {
            if(tot % i == 0) {
                if(judge(i, tot / i)) {
                    ans = min(ans, i);
                    return ;
                }
                if(judge(tot / i, i)) ans = min(ans, tot / i);
            }
        }
    }
    
    void solve() {
    
        int n;
        scanf("%d", &n);
    
        rep(i, 1, n) scanf("%d", &a[i]);
        rep(i, 1, n) scanf("%d", &c[i]);
    
        ans = INF;
    
        rep(i, 1, n) if(!vis[i]) dfs(i);
    
        rep(i, 1, n) vis[i] = 0;
    
        printf("%d
    ", ans);
    
    }
    
    
    int main() {
        int _; scanf("%d", &_);
        while(_--) solve();
    
    
    //    solve();
    
        return 0;
    }
    一步一步,永不停息
  • 相关阅读:
    UI21-多线程: GCD Grand Center Dispatch
    UI20- CollectionView瀑布流
    UI19-数据库操作:CoreDtata
    UI18-数据库操作:SQL FMDB
    UI17-数据库操作:SQLite
    UI16-通过Xcode将代码提交到github上, 把仓库放在github上
    UI15-存储路径
    UI14-沙盒机制,文件的读写,文件管理器的增删移动复制,归档和反归档。
    UI13-异步下载图片
    数据库相关中间件介绍
  • 原文地址:https://www.cnblogs.com/Willems/p/12561769.html
Copyright © 2020-2023  润新知