2021“MINIEYE杯”中国大学生算法设计超级联赛——H - Integers Have Friends 2.0

Posted H-w-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021“MINIEYE杯”中国大学生算法设计超级联赛——H - Integers Have Friends 2.0相关的知识,希望对你有一定的参考价值。

H-Integers_Have_Friends2.0

题意:

给出一个数组 a a a,找到一个最长的子序列 b b b,存在 m ( m > 1 ) m(m>1) m(m>1)使 b i   m o d   m = b j   m o d   m b_i~mod~m=b_j~mod~m bi mod m=bj mod m

思路:

我们先了解 x   m o d   m = y   m o d   m = z   m o d   m x~mod~m=y~mod~m=z~mod~m x mod m=y mod m=z mod m,则 g c d ( ∣ x − y ∣ , ∣ z − y ∣ ) > 1 gcd(|x-y|,|z-y|)>1 gcd(xy,zy)>1

证明:

假设 g c d ( ∣ x − y ∣ , ∣ z − y ∣ ) = 1 gcd(|x-y|,|z-y|)=1 gcd(xy,zy)=1 存在 m ( m > 1 ) m(m>1) m(m>1)使得 x   m o d   m = y   m o d   m = z   m o d   m x~mod~m=y~mod~m=z~mod~m x mod m=y mod m=z mod m

则: x = k 1 m + u , y = k 2 m + u , z = k 3 m + u x=k_1m+u,y=k_2m+u,z=k_3m+u x=k1m+u,y=k2m+u,z=k3m+u,所以 ∣ x − y ∣ = ∣ ( k 1 − k 2 ) m ∣ , ∣ z − y ∣ = ∣ ( k 3 − k 2 ) m ∣ |x-y|=|(k_1-k2)m|,|z-y|=|(k_3-k_2)m| xy=(k1k2)mzy=(k3k2)m,因为 m > 1 m>1 m>1,所以 g c d ( ∣ x − y ∣ , ∣ z − y ∣ ) > = m > 1 gcd(|x-y|,|z-y|)>=m>1 gcd(xy,zy)>=m>1

所以假设不成立,得证 x   m o d   m = y   m o d   m = z   m o d   m x~mod~m=y~mod~m=z~mod~m x mod m=y mod m=z mod m,则 g c d ( ∣ x − y ∣ , ∣ z − y ∣ ) > 1 gcd(|x-y|,|z-y|)>1 gcd(xy,zy)>1

现在我们从a数组中随机出两个数字,它们两个同时在最长子序列的概率很大,所以我们就随机选出两个数字,验证它们差值的全部质因子,返回在a数组中模数相同的个数。再取一个最大值。

#include <bits/stdc++.h>

using namespace std;
const int N = 2e6+10;
const int inf = 1e9+10;
typedef long long ll;
// #define int long long
const int K=30;
mt19937_64 gen(time(0));
ll a[N];
int p[N], tot;
bitset<N> st;
void init() {
    for(int i=2; i<N; i++) {
        if(!st[i]) p[tot++] = i;
        for(int j=0; j<tot&&1ll*i*p[j]<N; j++) {
            st[i*p[j]] = 1;
            if(i % p[j] == 0) break;
        }
    }
}
int n;
int C(ll pp, ll y) {
    int cnt = 0;
    for(int i=1; i<=n; i++) {
        if(a[i] % pp == y) cnt++; 
    }
    return cnt;
}
int main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif
    init();
    int t;
    scanf("%d", &t);
    while(t--) { 
        int k = 30, ans = 1;
        
        scanf("%d", &n);
        for(int i=1; i<=n; i++) scanf("%lld", &a[i]);
        while(k--) {
            int x, y;
            while(1) {
                x = gen() % n + 1;
                y = gen() % n + 1;
                if(x != y) break;
            }
            ll tmp = abs(a[x] - a[y]);
            for(int i=0; 1ll*p[i]*p[i]<=tmp; i++) {
                if(tmp % p[i] == 0) {
                    ans = max(ans, C(p[i], a[x]%p[i]));
                    while(tmp % p[i] == 0) tmp /= p[i];
                }
            }
            if(tmp > 1) ans = max(ans, C(tmp, a[x]%tmp));
        }
        printf("%d\\n", ans);
    }
}

以上是关于2021“MINIEYE杯”中国大学生算法设计超级联赛——H - Integers Have Friends 2.0的主要内容,如果未能解决你的问题,请参考以下文章

2021“MINIEYE杯”中国大学生算法设计超级联赛补题

2021“MINIEYE杯”中国大学生算法设计超级联赛题解

2021杭电多校赛2021“MINIEYE杯”中国大学生算法设计超级联赛签到题3题

2021“MINIEYE杯”中国大学生算法设计超级联赛

2021“MINIEYE杯”中国大学生算法设计超级联赛题解

6983 杭电多校(2021“MINIEYE杯”中国大学生算法设计超级联赛3) [记忆化搜索]