CodeForces - 615D Multipliers 费马小定理+组合数学

题目传送门:点击打开链接

题意:求出整数n的所有因子的乘积对1e9+7的模。

从题目中的给出的例子1·2·3·6 = 36  可以看出前面的式子可以写成 (1*6)*(2*3)=6*6=36,而n=6,所以我们可以想到答案可以是 (n)^m这种类型。m=n的因子个数除以2.

那么n的因子个数怎么求呢?根据题目给的数据,我们可以知道n的素因子种类可相应的个数,那我们可以假设 n的一个素因子为p,他的个数为np,那么这个素因子和其他的素因子组合的时候,我们可以取p的个数为 0-np,也就是(np+1)种可能,其他的也是这样,所以他们一共有(np1+1)(np2+1)....(npk+1).. 种可能,其中npi代表n中第i个素因子的个数,这个结果也就是n的因子个数。

但是有一种是例外的 那就是n可以开方的时候,例如 输入 2       5 5,由此可以知道n为25,1*5*25=125  和上面的情况不一样,我们可以直接25^(3/2)*sqrt(25), 但是n太大了,sqrt(n)不怎么好求。只好换个思路。。。。

所以我们现在要以n的素因子为思路,从(np1+1)(np2+1)....(npk+1).. 中我们还可以看到 对于 第一个素因子p1他的指数可以是  0-np1,也就是确定p1的指数 为t时,n的因子数还有(np2+1)....(npk+1)..所以我们可以得到n的因子连乘中 p1 的指数=(0+1+2+3...np1)*(np2+1)....(npk+1)..=(np1*(np1+1)/2)*(np2+1)....(npk+1)..那么其他的素因子的指数 也能得出。现在的问题是怎么求出对于每个pi素因子(np1+1)..(np(i-1)+1)*(np(i+1)+1)..(npk+1)..

第一种思路就是可以用两个数组l[],r[] ,l[i]表示的是(np1+1)*(np2+1)...(npi+1)%mod 的值,r[i]表示的是(npi+1)*(np(i+1)+1)....%mod 的值,那么对于每个素因子pi 就可以得到(npi*(npi+1)/2)*r[i+1]*l[i-1]

第二种思路就是改变一下乘的顺序,这个跟代码一起看比较好理解,对于素因子pi,先求出pi^[(npi*(npi+1)/2)*sum],sum表示(np1+1)*(np2+1)....(np(i-1)+1)%mod,然后在乘ans在对mod取余就可以了

对与pi^[(npi*(npi+1)/2)*sum]我们用费马小定理和快速幂就可以求了 pi^[(npi*(npi+1)/2)*sum]=pi^[(npi*(npi+1)/2)*sum%(mod-1)]

 代码为第二种:

<span style="font-family:Times New Roman, Times, serif;font-size:14px;">#include <iostream>
#include <cstring>
using namespace std;
typedef long long  ll;
const int maxn=2e5+100;
const int mod=1e9+7;
int m,cnt;ll sum;ll tol;
ll data[maxn],num[maxn];
ll quickmod(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1)
            ans=(ans*a)%mod;
        b/=2;
        a=a*a%mod;
    }
    return ans;
}

void init()
{
    cnt=0;
    memset(num,0,sizeof(num));
    for(int i=0;i<m;++i)
    {
        cin>>data[cnt];
        ++num[data[cnt]];
        if(num[data[cnt]]==1)
            ++cnt;
    }
    //cout<<cnt<<endl;
}
void solve()
{
    tol=1;
    sum=1;
    for(int i=0;i<cnt;++i)
    {
        ll tmp=quickmod(data[i],num[data[i]]*(num[data[i]]+1)/2);
        sum=(quickmod(sum,num[data[i]]+1)%mod)*quickmod(tmp,tol)%mod;
        tol=tol*(num[data[i]]+1)%(mod-1);
    }
    cout<<sum<<endl;
}
int main(int argc, const char * argv[])
{
    while(cin>>m)
    {
        init();
        solve();
    }
    return 0;
}
</span>

Time Limit: 2000MS Memory Limit: 262144KB 64bit IO Format: %I64d & %I64u

 Status

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

Input
2
2 3
Output
36
Input
3
2 3 2
Output
1728

Hint

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.



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值