zoukankan      html  css  js  c++  java
  • Codeforces-1327D Infinite Path

    Codeforces-1327D Infinite Path

    You are given a colored permutation (p_1, p_2, dots, p_n). The i-th element of the permutation has color (c_i).

    Let's define an infinite path as infinite sequence (i, p[i], p[p[i]], p[p[p[i]]] dots) where all elements have same color ((c[i] = c[p[i]] = c[p[p[i]]] = dots)).

    We can also define a multiplication of permutations a and b as permutation (c = a imes b) where (c[i] = b[a[i]]). Moreover, we can define a power k of permutation p as (p^k=underbrace{p imes p imes dots imes p}_{k ext{ times}}).

    Find the minimum (k > 0) such that (p^k) has at least one infinite path (i.e. there is a position i in (p^k) such that the sequence starting from i is an infinite path).

    It can be proved that the answer always exists.

    Input

    The first line contains single integer T ((1 le T le 10^4)) — the number of test cases.

    Next 3T lines contain test cases — one per three lines. The first line contains single integer n ((1 le n le 2 cdot 10^5)) — the size of the permutation.

    The second line contains n integers (p_1, p_2, dots, p_n (1 le p_i le n, p_i eq p_j for i eq j)) — the permutation p.

    The third line contains n integers (c_1, c_2, dots, c_n (1 le c_i le n)) — the colors of elements of the permutation.

    It is guaranteed that the total sum of n doesn't exceed (2 cdot 10^5).

    Output

    Print T integers — one per test case. For each test case print minimum k > 0 such that (p^k) has at least one infinite path.

    Example

    input

    3
    4
    1 3 4 2
    1 2 2 3
    5
    2 3 4 5 1
    1 2 3 4 5
    8
    7 4 5 6 1 8 3 2
    5 3 6 4 7 5 8 4
    

    output

    1
    5
    2
    

    Note

    In the first test case, (p^1 = p = [1, 3, 4, 2])and the sequence starting from (1: 1, p[1] = 1, dots) is an infinite path.

    In the second test case, $p^5 = [1, 2, 3, 4, 5] $and it obviously contains several infinite paths.

    In the third test case, (p^2 = [3, 6, 1, 8, 7, 2, 5, 4]) and the sequence starting from (4: 4, p^2[4]=8, p^2[8]=4, dots) is an infinite path since (c_4 = c_8 = 4).

    题意

    给定一个排列,每个元素有一个颜色,问最小的k,使得序列(p^k=underbrace{p imes p imes dots imes p}_{k ext{ times}})中存在一个无穷序列(i, p[i], p[p[i]], p[p[p[i]]] dots)

    题解

    首先,不考虑颜色,这个排列一定形成多个环,例如样例2,形成1->2->3->4->5->1的一个长度为5的环((p[1]=2,1到2,p[p[1]]=3dots),而这个(p^k)的操作,其实就相当于步长为k,在这个环上走(因为(p^k)就是(punderbrace{[p[p...]]}_k)),而有一个算是定理的东西就是,环长为(l),步长为k的话,那么所经过的点就是(起点+n*gcd(l,k))的点,所以我们对于一个环,我们没必要枚举所有的步长,只需要枚举为(l)因数的步长再枚举<因数的起点就可以枚举完所有的情况,对于枚举的起点,我们直接暴力check一遍整个环,看看颜色是否相同,颜色全部相同就更新答案,

    这样时间复杂度为:

    对于每个因子,枚举起点k,暴力check:(frac{l}k),这部分为(k*l/k=l),对于每个因子复杂度都是环长级别的,因子总个数不会太多,大概log级别,每个环都是(l*logl),对于所有的环,复杂度接近(nlogn),可以很轻松过掉,只跑了140ms+

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 2e5 + 50;
    int p[N], c[N];
    vector<int> a[N];
    int vis[N];
    int main() {
        int t; scanf("%d", &t);
        while (t--) {
            int n; scanf("%d", &n);
            for (int i = 1; i <= n; i++) vis[i] = 0, a[i].clear();
            for (int i = 1; i <= n; i++) scanf("%d", &p[i]);
            for (int i = 1; i <= n; i++) scanf("%d", &c[i]);
            int cnt = 0;
            for (int i = 1; i <= n; i++) {
                if (!vis[i]) {
                    vis[i] = 1;
                    a[++cnt].push_back(i);
                    int now = i;
                    while (1) {
                        now = p[now];
                        vis[now] = 1;
                        if (now != i) a[cnt].push_back(now);
                        else break;
                    }
                }
            }
            int ans = 1e9;
            for (int i = 1; i <= cnt; i++) {
                for (int j = 1; j <= a[i].size(); j++) {
                    if (a[i].size() % j == 0) {
                        
                        for (int x = 0; x < j; x++) {
                            int cc = c[a[i][x]];
                            bool flag = true;
                            for (int k = x; k < a[i].size(); k += j) {
                                if (c[a[i][k]] != cc) {
                                    flag = false;
                                    break;
                                }
                            }
                            if (flag) ans = min(ans, j);
                        }
                    }
                }
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
    

    附带一道水题e题

    Codeforces-1327E Count The Blocks

    题意

    给定一个n,求(10^n-1)以内所有数写成长度为n的数(不足前缀补0),长度为i的数字块个数分别为多少

    题解

    先考虑n=1,那么长度块只可能为1,个数为10个

    在考虑n=2,那么长度总共为100*2=200个,长度为2的数字块等于在长度为1的数字块基础上加上一个与第一个数字相同的数字,所以数量等于n=1时长度为1的数字块数量,那么长度为2的字块数量即为总长度减去(2*长度为2的数量)

    考虑n=k,那么总长度即为10^k*k,长度为n的字块数量等于n=k-1时长度为n-1的字块数量(加一个相同的数字),其他同理,都是加一个相同的数字使其长度加一,这样我们就可以直接递推,维护两个前缀和即可

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 2e5 + 50;
    typedef long long ll;
    const ll mod = 998244353;
    ll ans[N];
    ll suf1[N];
    ll suf2[N];
    int main() {
        int n;
        scanf("%d", &n);
        ans[n] = 10;
        ll base = 10;
        
        ll cnt = 1;
        suf1[n] = 10;
        suf2[n] = 10;
        for (int i = n - 1; i >= 1; i--) {
            base = base * 10 % mod;
            cnt++;
            ll xbase = base * cnt % mod;
            ans[i] = (xbase - suf1[i + 1] - suf2[i + 1] + mod + mod) % mod;
            suf1[i] = (suf1[i + 1] + ans[i] + mod) % mod;
            suf2[i] = (suf2[i + 1] + suf1[i] + mod) % mod;
        } 
        for (int i = 1; i <= n; i++) printf("%lld ", ans[i] % mod)
        return 0;
    }
    
  • 相关阅读:
    Container With Most Water(LintCode)
    Single Number III(LintCode)
    Single Number II(LintCode)
    Spiral Matrix(LintCode)
    Continuous Subarray Sum II(LintCode)
    kubernetes外部访问的几种方式
    kubernetes 数据持久化
    kubernetes deployment
    kubernetes service访问原理
    kubernetes namespace
  • 原文地址:https://www.cnblogs.com/artoriax/p/12564515.html
Copyright © 2011-2022 走看看