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 \times b\) where \(c[i] = b[a[i]]\). Moreover, we can define a power k of permutation p as \(p^k=\underbrace{p \times p \times \dots \times p}_{k \text{ 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 \neq p_j for i \neq 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 \times p \times \dots \times p}_{k \text{ 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]]=3\dots\),而这个\(p^k\)的操作,其实就相当于步长为k,在这个环上走(因为\(p^k\)就是\(p\underbrace{[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\n", 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;
}
posted @ 2020-03-25 10:45  Artoriax  阅读(140)  评论(0编辑  收藏  举报