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(∣x−y∣,∣z−y∣)>1
证明:
假设 g c d ( ∣ x − y ∣ , ∣ z − y ∣ ) = 1 gcd(|x-y|,|z-y|)=1 gcd(∣x−y∣,∣z−y∣)=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| ∣x−y∣=∣(k1−k2)m∣,∣z−y∣=∣(k3−k2)m∣,因为 m > 1 m>1 m>1,所以 g c d ( ∣ x − y ∣ , ∣ z − y ∣ ) > = m > 1 gcd(|x-y|,|z-y|)>=m>1 gcd(∣x−y∣,∣z−y∣)>=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(∣x−y∣,∣z−y∣)>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的主要内容,如果未能解决你的问题,请参考以下文章