1. 程式人生 > >【JZOJ B組】腐敗

【JZOJ B組】腐敗

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

思路

可以發現,每一個質因子的貢獻可以單獨拿出來算
求出每一個數有多少質因子p,然後兩兩配對(可以優化到O(能過))

最後會剩下一些較大的質數,我們可以排個序,若a[i]==a[i-1]則會產生貢獻

程式碼

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=3e4+77;
const ll mod=100000000009;
int a[maxn],b[maxn+77],c[maxn],cnt,z[maxn],n;
ll ans=1;
ll mult(ll x,ll t)
{
	if(x<t) swap(x,t);
	ll p=0;
	while(t)
	{
		if(t&1) p=(p+x)%mod; 
		t>>=1; x=(x+x)%mod;
	}
	return p;
}
ll power(ll x,ll t)
{
	ll p=1;
	while(t)
	{
		if(t&1) p=mult(p,x)%mod;
		t>>=1; x=mult(x,x)%mod;
	}
	return p;
}
void init()
{
	for(int i=2; i<=maxn; i++)
	{
		if(!b[i]) z[++cnt]=i;
		for(int j=1; j<=cnt; j++) 
		{
			if(i*z[j]>maxn) break;
			b[i*z[j]]=1;
			if(i%z[j]==0) break;
		}
	}
}
int main()
{
	init();
	scanf("%d",&n);
	for(int i=1; i<=n; i++) scanf("%d",&a[i]);
	for(int i=1; i<=cnt; i++)
	{
		memset(b,0,sizeof(b));
		for(int j=1; j<=n; j++)
		{
			while(a[j]%z[i]==0)
			{
				a[j]/=z[i]; b[j]++;
			}
		}
		for(int j=1; j<=n; j++) c[b[j]]++;
		b[0]=0;
		for(int j=0; j<=50; j++) for(; c[j]; b[++b[0]]=j,c[j]--);
		ll sum=0;
		for(int j=1; j<=n; j++) sum+=1ll*b[j]*(n-j+1);
		ans=mult(ans,power(z[i],sum));
	}
	sort(a+1,a+n+1);
	int p=1;
	for(int i=1; i<=n; i++)
	{
		if(a[i]!=a[i-1]) p=i;
		ans=mult(ans,power(a[i],i-p+1));
	}
	printf("%lld",ans);
}