Codeforces Round #338 (Div. 2)D. Multipliers【费马小定理+组合数学】

D. Multipliers
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Ayrat has number n, represented as it's prime factorization pi of size m, i.e. n = p1·p2·...·pm. Ayrat got secret information that that the product of all divisors of n taken modulo 109 + 7 is the password to the secret data base. Now he wants to calculate this value.

Input

The first line of the input contains a single integer m (1 ≤ m ≤ 200 000) — the number of primes in factorization of n.

The second line contains m primes numbers pi (2 ≤ pi ≤ 200 000).

Output

Print one integer — the product of all divisors of n modulo 109 + 7.

Examples
input
2
2 3
output
36
input
3
2 3 2
output
1728
Note

In the first sample n = 2·3 = 6. The divisors of 6 are 123 and 6, their product is equal to 1·2·3·6 = 36.

In the second sample 2·3·2 = 12. The divisors of 12 are 12346 and 121·2·3·4·6·12 = 1728.

参考:http://blog.csdn.net/viphong/article/details/50615502

一个数的素因子为p1,p2,p3.....其数量为t[1],t[2]....t[n],共 kind种素数那么这个数的因子个数为 sum=(t[1]+1)*(t[2]+1)*****(t[n]+1);  
求出每一个素因子对答案的贡献,对一个素因子P[i]则数N中包含素因子p[i]的数有p[i]出现一次与的因数的个数为剩下的因子的素因子的个数,出现两次的因数的个数同为其其它的因数的个数。最后这些因数将最终乘在一起所以可以计算出素因子p[i]总共被乘的(1+2+...+t[i])*(不包含素因子p[i]的因数的个数==sum/(t[i]+1))

所以可得素因子p[i]的贡献为p[i]^((t[i]*(t[i]+1)/2)*(sum/(t[i]+1)));

费马小定理  :假如p是素数,且a与p互质,那么a^(p-1) = 1 (mod p)。
由此可以推得 a^x%p==> a^(x%(p-1))%p考虑x会非常的大且还有除2操作,所以对其取余之后再除2则结果可能不正确,因此可以对(2*MOD-2)取余即可。
/* ***********************************************
Author       : ryc
Created Time : 2016-08-12 Friday
File Name    : E:\acm\codeforces\367D.cpp
Language     : c++
Copyright 2016 ryc All Rights Reserved
************************************************ */
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<list>
#include<vector>
#include<map>
#include<string>
#define MOD 1000000007ll
using namespace std;
const int maxn=200010;
typedef long long LL;
LL t[maxn];
LL Pow(LL a,LL b){
    if(b==0)return 1%MOD;
    long long temp=Pow(a,b>>1);
    temp=temp*temp%MOD;
    if(b&1)temp=temp*a%MOD;
    return temp;

}
int main()
{
    LL n,m;cin>>m;
    for(LL i=1;i<=m;++i){
        scanf("%lld",&n);t[n]++;
    }
    LL sum=1;
    for(int i=1;i<maxn;++i){
        if(t[i])sum=sum*(t[i]+1)%(2*MOD-2);
    }
    LL ans=1;
    for(LL i=1;i<maxn;++i){
        if(t[i]){
            ans=ans*Pow(i,sum*t[i]/2ll%(MOD-1))%MOD;
        }
    }
    printf("%lld\n",ans);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值