hdu-5525 Product(费马小定理)

题目来源:http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=644&pid=1003





前面用奇偶性约掉2,后面处理前缀积和后缀积。

WA了很久的地方:在约掉2之前不能模(mod-1)

#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
using namespace std;
typedef long long LL;
const int N = 100001;
LL Mod = 1000000007;
LL mod = Mod - 1;
char vis[N];
int prime[N];
vector<int> G[N];
int tot = 0;
void init_prime()
{
    memset(vis, 0, sizeof(vis));
    for(int i=2; i<N; i++)
    {
        if(!vis[i])
        {
            prime[++tot] = i;
            for(int j=i; j<N; j+=i)
            {
                vis[j] = 1;
                G[j].push_back(i);
            }
        }
    }
} 

LL quick(LL a, LL b)
{
    LL c =  1;
    while(b)
    {
        if(b&1)
            c = c * a % Mod;
        b >>= 1;
        a = a * a % Mod;
    }
    return c;
}
int a[N];
LL num[N];    //素数i的个数 
LL pre[N], suf[N];

int main()
{
    init_prime();
    int i, j, k, m, n;
    while(scanf("%d", &n) == 1)
    {
        for(i=1; i<=n; i++)
            scanf("%d", a+i);
            
        memset(num, 0, sizeof(num));
        
        for(i=1; i<=n; i++)
        {
            for(j=0; j<G[i].size(); j++)
            {
                int tp = 0, x = i;
                while(x%G[i][j] == 0)
                {
                    tp ++;
                    x /= G[i][j];
                }
                num[G[i][j]] += a[i] * tp;
            }
        }
            
        ///处理(p1+1)*(p2+1)*...*(px+1)的前缀积和后缀积    
        pre[0] = 1;
        for(int i=1; i<=tot; i++)
        {
            pre[i] = pre[i-1];
            if(num[prime[i]]) 
                pre[i] = pre[i] * (num[prime[i]] % mod +1) % mod;
        }
        suf[tot+1] = 1;
        for(int i=tot; i>=1; i--)
        {
            suf[i] = suf[i+1];
            if(num[prime[i]])
                suf[i] = suf[i] * (num[prime[i]] % mod +1) % mod;
        } 
        /*---------------------------------------------*/
        
        LL ans = 1;
        for(int i=1; i<=tot; i++)
        {
            LL tmp, p = num[prime[i]];    
            if(p & 1)
                tmp = p % mod * (((p+1)>>1) % mod) % mod;
            else 
                tmp = (p>>1) %mod * ((p+1) % mod) % mod;
            ans = ans * quick(prime[i], tmp * pre[i-1] % mod * suf[i+1] % mod) % Mod;
        }
        printf("%I64d
", ans);
    }
    return 0;    
}
原文地址:https://www.cnblogs.com/WCB-ACM/p/5269613.html