小D的序列

题目描述

小D今天学习了哈希,因此她对一个等比数列在模意义下的值产生了浓厚兴趣。她选定了三个数 \(n,a,p\ (0<a<p)\) ,并生成了一个共 n 项且下标从 0 开始的序列\(f_i=a^i\!\!\mod p\) 用于研究。但可惜的是,她不小心把 f 排序了一下,并且她忘记了原先的 a 的值,请你告诉她原先的 a 等于几。
注:题目描述中并没有包含部分限制条件,请仔细阅读限制与约定。

输入格式

第一行输入两个数 n,p ,表示数组长度和模数。
第二行输入 n 个数,第 i 个数为 \(f'_{i-1}\)其中序列 \(f'\)是序列 $f $排序后的内容。

输出格式

一行一个整数 a,表示原定的底数。

解析

等比数列\(a ^ 0, a ^ 1,...,a ^{ n - 1}\)\(a ^ 1\)一定在f序列中(因为a<mod),所以我们可以枚举f序列中的每一个数,假设他是a并且判断一下。注意判断时加上另一个条件:\(a' ^ {n(n-1)/2} = a ^0 * a ^ 1 *...*a ^ {n - 1}\)

代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e5 + 10, inf = 1e9 + 10;
int n, p, a[N];
bool vis[N];
int qpow(int x, int k) {
	int ans = 1; 
	while (k) {
		if (k & 1) ans = 1ll * ans * x % p;
		x = 1ll * x * x % p;
		k >>= 1;
	}
	return ans;
}
bool check(int x) {
	memset(vis, 0, sizeof vis);
	for (int i = 1; i <= n; i ++) {
		int v = qpow(x, i - 1);
		int p = lower_bound(a + 1, a + n + 1, v) - a;
		if (vis[p] == 1) return 0;
		if (a[p] != v) return 0;
		else vis[p] = 1;
	}
	return 1;
}
signed main() {
	ios::sync_with_stdio(false); cin.tie(0);
	cin >> n >> p; int mul = 1;
	for (int i = 1; i <= n; i ++) {
		cin >> a[i];
		mul = 1ll * mul * a[i] % p;
	}
	int up = 1ll * n * (n - 1) / 2;
	for (int i = 1; i <= n; i ++) {
		if (qpow(a[i], up) == mul) {
			if (check(a[i])) {
				cout << a[i] << '\n';
				return 0;
			}
		}
	}
	return 0;
}

image

posted @ 2022-10-13 08:03  YHXo  阅读(137)  评论(0)    收藏  举报