D
jxustoj2344
思路:
n = p1 ^ k1 * p2 ^ k2 ***** pm ^ km
n所有因子的乘积为 x[1] * x[2] *** x[w] (w为因子个数) = p[1] ^ j1 * p[2] ^ j2 ***p[m]^jm
相当于将所有因子分解质因数的到的形式。
那么需要计算p[i] 的指数 ji
考虑输入的第i个质数因子 , cnt[i] 代表第i个质数的次数。
对于第 i 个质数 ,他可以跟前后的素因子共同组成某一个n的因子,组合方式共有
pre[i-1] * rear[i+1] * num ;
其中pre[i-1] 代表前i-1个素因子可以组成因子的种数,rear[i+1]代表后i+1个素因子可以组成的因子的种数,num则为第 i 个因子的可能出现次数的所有情况 ( 0 + 1 + 2 +…+ cnt[i] ) = cnt[i] * ( cnt[i] + 1 ) / 2 ;
这样可以得到任意p[i]的指数 ji
结果就是p[1] ^ j1 * p[2] ^ j2 ***p[m]^jm,虽然得到ji但是指数过大,可以用费马小定理,将指数% ( MOD -1 )
Code:
#include
#define LL long long
using namespace std;
const int AX = 2e5 + 666 ;
const int MOD = 1e9 + 7 ;
LL quick( LL a, LL b ){
LL ans = 1LL ;
while( b ){
if( b & 1 ) ans = ( ans * a ) % MOD ;
b >>= 1 ;
a = ( a * a ) % MOD ;
}
return ans % MOD ;
}
int p[AX] ;
LL cnt[AX] = {0LL};
LL pre[AX];
LL rear[AX];
int main(){
int n ;
scanf("%d",&n) ;
int x ;
int num = 0 ;
for( int i = 0 ; i < n ; i++ ){
scanf("%d",&x);
if( !cnt[x] ) p[++num] = x ;
cnt[x] ++ ;
}
//sort( p + 1 , p + num + 1 ) ;
pre[0] = 1LL ;
rear[num+1] = 1LL ;
for( int i = 1 ; i <= num ; i++ ){
pre[i] = ( 1LL * pre[i-1] * ( cnt[p[i]] + 1 ) ) % ( MOD - 1 ) ;
}
for( int i = num ; i >= 1 ; i-- ){
rear[i] = ( 1LL * rear[i+1] * ( cnt[p[i]] + 1 ) ) % ( MOD - 1 ) ;
}
LL res = 1LL ;
for( int i = 1 ; i <= num ; i++ ){
LL c = cnt[p[i]] ;
if( !c ) continue ;
LL sum = pre[i-1] * rear[i+1] % ( MOD - 1 ) ;
LL tmp = ( 1LL * c * ( c + 1 ) / 2 % ( MOD - 1 ) * sum ) % ( MOD - 1 ) ;
res = ( res * quick( p[i] , tmp ) ) % MOD ;
}
printf("%I64d\n",res);
return 0 ;
}