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 1, 2, 3 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 1, 2, 3, 4, 6 and 12. 1·2·3·4·6·12 = 1728.

题意:给你 n 个素数,让你求它们相乘之后的数的因子之积

思路:首先,我们知道一个数n可以分解成 pc11pc22....pckk ,其中 p 为素数,c为当前素数出现的次数, n 的因子个数sum= ki=1(1+ci) ,那么我们可以分析每个素因子 p 对于答案的贡献:
不含p的因子的个数为 sumc+1 ,而只含有 p 的因子为p1,p2....pc,那么每一个组合都会和不含 p 的因子进行结合,那么每一种组合出现的次数为sumc+1次,那么当前p对于答案的贡献为 (ci=1pi)(sumc+1) ,进行化简得: p(1+2+...+c)(sumc+1) = pc(c+1)2sumc+1 = pcsum2 .求出每种素数对于答案的贡献之后,将它们相乘即为所得。但是又出现一个问题,在运算过程中我们不断的进行取模, sum 的值有可能为奇数,也有可能为偶数,所以说当sum为偶数的时候, sum%mod 为奇数,那么对后面的 pcsum2 是可能有影响的,因为 sum 要除以2,所以我们根据费马小定理: ap1%p=1 ,可以将对 sum 的取余过程变为对一个偶数取余,最后的结果是不变的,可以将 mod 变成 2mod2 sum 取模,这样,问题就解决了。

最后总结我们需要进行的两个步骤:
1. sum=ki=1(1+ci)%(2mod2)
2. ans=ki=1pcisum2i%mod

ac代码:

/* ***********************************************
Author       : AnICoo1
Created Time : 2016-08-12-09.38 Friday
File Name    : C:\Users\lenovo\Documents\2016-8-12.cpp
LANGUAGE     : C++
Copyright  2016 clh All Rights Reserved
************************************************ */
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stack>
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<iostream>
#include<algorithm>
#define MAXN 1010000
#define LL long long
#define ll __int64
#define INF 0xfffffff
#define mod 1000000007
#define mem(x,y) memset(x,(y),sizeof(x))
#define PI acos(-1)
#define eps 1e-8
using namespace std;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
ll powmod(ll a,ll b,ll MOD){ll ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
double dpow(double a,ll b){double ans=1.0;while(b){if(b%2)ans=ans*a;a=a*a;b/=2;}return ans;}
//head
ll cnt[MAXN];
int main()
{
    int n;scanf("%d",&n);mem(cnt,0);
    for(int i=1;i<=n;i++)
    {
        int p;scanf("%d",&p);
        cnt[p]++;
    }
    ll sum=1;
    for(int i=1;i<=200000;i++)
    {
        if(cnt[i])
            sum=(sum*(1+cnt[i]))%(mod*2-2);
    }
    ll ans=1;
    for(int i=1;i<=200000;i++)
        if(cnt[i])
            ans=(ans*powmod(i,cnt[i]*sum/2,mod))%mod;
    printf("%I64d\n",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值