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;
}
原文地址:https://www.cnblogs.com/artoriax/p/12564515.html