hdoj 5525 Product 【组合数学+质因子处理】

Product

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 894    Accepted Submission(s): 206


Problem Description
Given a number sequence  A1,A2....An ,indicating  N=ni=1iAi .What is the product of all the divisors of N?
 

Input
There are multiple test cases.
First line of each case contains a single integer n. (1n105)
Next line contains n integers  A1,A2....An ,it's guaranteed not all  Ai=0 . (0Ai105) .
It's guaranteed that  n500000 .
 

Output
For each test case, please print the answer module  109+7  in a line.
 

Sample Input
  
  
4 0 1 1 0 5 1 2 3 4 5
 

Sample Output
  
  
36 473272463
 


CFcopyBC? 不过难度减少了。

题意:给你1-n的因子个数num[i],有N = num[1] * num[2] * ... * num[n], 问N所有因子乘积%1000000007.


思路:先处理出所有质因子,然后组合数学就ok了。


AC代码:577ms


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <string>
#define INF 0x3f3f3f3f
#define eps 1e-8
#define MAXN (100000+10)
#define MAXM (200000+10)
#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define Pi(a) printf("%d\n", (a))
#define Pf(a) printf("%.2lf\n", (a))
#define Pl(a) printf("%lld\n", (a))
#define Ps(a) printf("%s\n", (a))
#define W(a) while(a--)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define MOD 1000000007
#define LL long long
#define lson o<<1, l, mid
#define rson o<<1|1, mid+1, r
#define ll o<<1
#define rr o<<1|1
#define PI acos(-1.0)
using namespace std;
LL cnt[MAXN];
const int mod = MOD-1;
LL l[MAXN], r[MAXN];
LL pow_mod(LL a, LL n)
{
    LL ans = 1;
    while(n)
    {
        if(n & 1LL)
            ans = ans * a % MOD;
        a = a * a % MOD;
        n >>= 1;
    }
    return ans;
}
bool vis[MAXN];
vector<int> G[MAXN];
void getprime()
{
    //CLR(vis, false);
    for(int i = 2; i <= 100000; i++)
    {
        if(vis[i]) continue;
        G[i].push_back(i);
        for(int j = 2*i; j <= 100000; j+=i)
        {
            vis[j] = true;
            G[j].push_back(i);
        }
    }
    vis[1] = true;
}
int main()
{
    getprime();
    int n;
    while(Ri(n) != EOF)
    {
        for(int i = 1; i <= n; i++)
        {
            int num; Ri(num);
            if(num == 0 || i == 1) continue;
            if(vis[i])
            {
                int p = i;
                for(int j = 0; j < G[i].size(); j++)
                {
                    int m = 0;
                    while(p % G[i][j] == 0)
                    {
                        p /= G[i][j];
                        m++;
                    }
                    cnt[G[i][j]] += num * m;
                }
            }
            else
                cnt[i] += num;
        }
        l[0] = r[n+1] = 1; cnt[0] = 0;
        for(int i = 1; i <= n; i++)
            l[i] = l[i-1] * (cnt[i] + 1) % mod;
        for(int i = n; i >= 1; i--)
            r[i] = r[i+1] * (cnt[i] + 1) % mod;
        LL ans = 1;
        for(int i = 1; i <= n; i++)
        {
            if(cnt[i] == 0 || vis[i]) continue;
            LL num = l[i-1] * r[i+1] % mod;
            LL a = cnt[i]+1; LL b = cnt[i];
            if(a & 1) b /= 2;
            else a /= 2;
            a %= mod; b %= mod;//这里好坑。。。
            num = a * b % mod * num % mod;
            ans = ans * pow_mod(i, num) % MOD;
            cnt[i] = 0;
        }
        printf("%I64d\n", ans);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值