版权声明:本文为博主原创文章,未经博主允许不得转载。 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);
}