jzoj4668. 腐败(数论)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhanghaoxian1/article/details/83500570

4668. 腐败

Description

在这里插入图片描述

Input
第一行一个正整数n,表示序列长度
第二行n个正整数,为给出的序列A

Output
一个非负整数,为答案。

Sample Input
3
6 4 12

Sample Output
13824

Data Constraint
50%:n<=3000;
100%:n<=30000,A[i]<=10^7

分析:考虑每个质因数的贡献,分解质因数,对于根号 n 以内的某个质因数,我们可以根据原序列得到一个指数序列。
排个序然后乱搞一下···
枚举每个位置,他与后面的数的 gcd 肯定不超过自己,所以就直接 O(1)把自己与后面的 gcd
加入答案。对于根号 n 以外的质因数,直接枚举即可。

代码

#include <cstdio>
#include <cmath>
#include <algorithm>
#define ll long long
#define mo 100000000009
#define N 40000
using namespace std;

int n;
ll a[N],b[N],num[N];
int p[N];
ll ans, X;

void prime()
{
	for (int i = 2; i <= sqrt(X); i++)
	{
		bool fl = false;
		for (int j = 2; j < i; j++)
			if (i % j == 0)
			{
				fl = true;
				break;
			}
		if (!fl) p[++p[0]] = i;
	}
}

ll mul(ll x, ll y)
{
	ll a1 = x / X, a2 = x % X;
	ll b1 = y / X, b2 = y % X;
	ll sum = (a1 * X % mo * b1 % mo * X % mo);
	sum = (sum + a2 * b1 % mo * X % mo) % mo;
	sum = (sum + a1 * b2 % mo * X % mo) % mo;
	sum = (sum + a2 * b2 % mo) %mo;
	return sum;
}

ll ksm(ll x, ll y)
{
	ll base = x, r = 1;
	while (y)
	{
		if (y & 1) r = mul(r, base);
		base = mul(base, base);
		y /= 2;
	}
	return r;
}

int main()
{
	X = 1e7;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
	prime();
	ans = 1;
	for (int i = 1; i <= p[0]; i++)
	{
		for (int j = 0; j <= n; j++) b[j] = num[j] = 0;
		for (int j = 1; j <= n; j++)
			while (a[j] % p[i] == 0) b[j]++, a[j] /= p[i];
		for (int j = 1; j <= n; j++) num[b[j]]++;
		b[0] = 0;
		for (int j = 0; j <= 30; j++) 
			while (num[j]--) b[++b[0]] = j;
		ll sum = 0;
		for (int j = 1; j <= n; j++) sum += b[j] * (n - j + 1);
		ans = mul(ans, ksm(p[i], sum));
	}
	sort(a + 1, a + n + 1);
	int las = 1;
	for (int i = 1; i <= n; i++)
	{
		if (a[i] != a[i - 1]) las = i;
		ans = mul(ans, ksm(a[i], i - las + 1));
	}
	printf("%lld\n", ans);
}

猜你喜欢

转载自blog.csdn.net/zhanghaoxian1/article/details/83500570
今日推荐