题目连接
http://codeforces.com/contest/615/problem/D
Description
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.
Sample Input
3
2 3 2
Sample Output
1728
题意
给出一个数的所有素因子,问这个数所有因子的积是多少,结果对1e9+7取余。
题解
可以看成是组合问题,例如 2^3 3^2 5^2,这是一个数的所有素因子,那出现2的因子就是2^1,2^2,2^3依次和其他所有其他素因子组合,对于素因子3就有3种选择,0,1,2。对于5也有3种选择,0,1,2。2的1次幂,2次幂,3次幂与这些数组合,高斯公式求和…。(3+1)* 3/2 * (2+1)*(2+1),这个就是2的幂次,因为幂次可能特别大,用费马小定理处理下,mod(1e9+6),然后在快速幂。 //pow1代表素因子2的个数
可以注意到,所有的数都要算num+1的积的,即p= (pow2+1)* (pow3+1)……* (pown+1) ,这个p在计算每个素因子的幂次的时候都要用到,我们可以提前算出来,这样就不用前缀+后缀那么算了。然后在 * pown/2//素因子n的个数。
其中很坑的地方,mut=mut* (it->second+1)%(2* (MOD-1)) 我感觉是我不用前缀和后缀才会出现这样奇怪的问题,为什么是mod二倍呢,后来看了别人代码,想了很久才明白。因为可能出现比如 22 mod 12 然后是* 2 /是4.。。这样按原先算,就是10*2/4mod(MOD)=5,但是按后一种方法算是22 *2/4mod(MOD)=11,为什么会这样呢?因为第一步正常取模以后的值是小于MOD的,如果后面的操作总体是<1的 即2/4是小于1的,但如果总体是大于1的就没有问题,因为反正都是算出来大于MOD在取余的,那相当于就是在给一个已经小于MOD的值做操作,这样是错误的。但其实我们应该是开始有一个大于MOD的值,进行一系列操作以后仍大于MOD在取余,得到我们的答案。
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll MOD=1e9+7;
ll fastpow(ll a,ll b,ll mod) //快速幂
{
ll res=1;
ll x=b;
while(a>0)
{
if(a&1)res=((res%MOD)*(x%MOD))%MOD;
x=((x%MOD)*(x%MOD))%MOD;
a/=2;
}
return res;
}
int main()
{
ll n;
scanf("%I64d",&n);
map<long long,long long>s;
ll sum=0, mut=1;
for(ll i=0;i<n;i++)
{
ll v;
scanf("%I64d",&v);
s[v]++; //统计素因子个数
}
map<long long,long long>::iterator it=s.begin();
for(;it!=s.end();it++) //费马小定理处理幂次
{
mut=mut*(it->second+1)%(2*(MOD-1));//最坑的地方,%(2*(MOD-1))具体解释看上面
}
ll ans=1;
it=s.begin();
for(;it!=s.end();it++)
{
ll x=it->first;
ll kk=it->second;
ll y=mut*kk/2%(MOD-1); //处理幂次
ll t=fastpow(y,x,1e9+7)%MOD;
ans=((ans%MOD)*(t%MOD))%MOD;
}
printf("%I64d\n",ans);
return 0;
}