1. 程式人生 > >hdu 5525 Product (費馬小定理優化的快速冪)

hdu 5525 Product (費馬小定理優化的快速冪)

@(K ACMer)

題意:
給你一個n個數的數列:an. 求

i=1niai%mod

分析:
知識補充:
- 一個數的約數的個數等於:

(p1+1)(p2+1)....(pn+1)(pi)
- 根據費馬小定理:如果mod是素數,且a不是mod的倍數有:ap1%p=1那麼易得:ak%mod=ak%(mod1)%mod這樣就可以把超大的指數變小,進而來用快速冪計算.

回到這個題,我們先把所有的質因子和他的次數算出來,然後每一個質因子被利用的次數等於其它不含該因子的質數所能構成的約數的個數乘以:(1+2+3+....+n

)==n(n+1)2
在計算其他約數個數的時候我們用了記錄字首字尾的技巧,在處理除2取餘的時候,我們用了判斷相鄰數奇偶性的技巧,具體看程式碼.

#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <map>
#include <stack>
#include <vector>
#include <string>
#include <queue>
#include <cstdlib>
#include <cmath> #include <algorithm> using namespace std; typedef pair<int, int> pii; typedef long long ull; typedef long long ll; typedef vector<int> vi; #define xx first #define yy second #define rep(i, a, n) for (int i = a; i < n; i++) #define sa(n) scanf("%d", &(n))
#define vep(c) for(decltype((c).begin()) it = (c).begin(); it != (c).end(); it++) const int mod = int(1e9) + 7, INF = 0x3fffffff, maxn = 1e5 + 12; int n, a[maxn], b[maxn], prim[maxn / 10], cnt; ll sum, t; ll mp[maxn], suffix[maxn / 10], prefix[maxn / 10]; void getit(void) { memset(b, 1, sizeof(b)); rep (i, 2, maxn) { if (b[i]) { prim[cnt++] = i; for (int j = i; j < maxn; j += i) b[j] = 0; } } } int pows(ll y, ll n) { ll ret = 1; while (n) { if (n & 1) ret = ret * y % mod; y = y * y % mod; n >>= 1; } return int(ret % mod); } void doit(int x, int y) { if (y == 0) return; for (int i = 0; prim[i] * prim[i] <= x; i++) { if (x % prim[i] == 0) { ll tt = 0; while (x % prim[i] == 0) { tt += y; x /= prim[i]; } mp[prim[i]] += tt; } } if (x != 1) mp[x] += y; } int mul(ll x) { ll a = x, b = x + 1; if (a % 2) b /= 2; else a /= 2; return (a % (mod - 1)) * (b % (mod - 1)) % (mod - 1); } int main(void) { getit(); while (~sa(n)) { rep (i, 0, n) { sa(a[i]); } memset(mp, 0, sizeof(mp)); sum = 1, t = 1; rep (i, 2, n + 1) { doit(i, a[i - 1]); } suffix[cnt - 1] = prefix[0] = 1; rep (i, 1, cnt) prefix[i] = prefix[i - 1] * (mp[prim[i - 1]] + 1) % (mod - 1); for (int i = cnt - 2; i >= 0; i--) suffix[i] = suffix[i + 1] * (mp[prim[i + 1]] + 1) % (mod - 1); ll ans = 1; rep (i, 0, cnt) { ll temp = pows(prim[i], (prefix[i] * suffix[i] % (mod - 1)) * mul(mp[prim[i]]) % (mod - 1)); ans = ans * temp % mod; } printf("%lld\n", ans); } return 0; }