D. Multipliers——Codeforces Round #338 (Div. 2)

D. Multipliers

题目链接

题目大意

给出\(n\)个质数,求这\(n\)个数的乘积\(m\)的所有因子(不重复)之积。

解题思路

首先想到可以对最终的\(m\)进行质因子分解,但是因为给出的是质数,所以直接统计每个质数出现的次数即可。
计算所有因子的数量:\(sum = \prod_{i = 1}^{p} (cnt_i + 1)\),即有\(p\)个不同的质因子,\(cnt_i\)是第\(i\)个质因子出现的次数。
对于每一个质因子,计算对答案的贡献,
对于第\(i\)个质因子\(p_i\),此时将因子集合分成两部分,即有\(p\)和没有\(p\)的,没有\(p\)的数量分别为\(sum/(1 + cnt_i)\)\(p\)对答案的贡献为\(p\)可以和另外一个集合组成的所有数,都是\(m\)的因子,所以贡献为\((\prod_{i = 1}^{cnt_i}p^{i})^{\cfrac {sum}{cnt_i + 1}}\),化简:

\[p^{\cfrac{cnt_i*(cnt_i + 1)}{2} * \cfrac{sum}{cnt_i + 1}} = p^{\cfrac{sum*cnt_i}{2}} \]

这里\(sum\)有可能是奇数则除\(2\)会影响,所以需要将 \(sum\)\(cnt\)
保证为偶数,因为由费马小定理:\(a^x \%% p = a^{x%(p - 1)} % p\)
所以我们可以将\(sum\)\(2 * (p - 1)\)取模,因为\(sum\)本质上是作为幂数的,如果存在一个\(cnt_i\)是奇数,那么\(sum\)必是偶数,并且每次都对一个偶数取模,最后结果也一定是偶数,如果\(cnt_i\)全是偶数,则\(cnt_i/2\)直接就满足题意了,所以\(sum\)只需要对\(2*(p - 1)\)取模即可。

最后答案即是所有质因子的贡献乘积。

Code

#include <bits/stdc++.h>
#define ll long long
#define qc ios::sync_with_stdio(false); cin.tie(0);cout.tie(0)
#define fi first
#define se second
#define PII pair<int, int>
#define PLL pair<ll, ll>
#define pb push_back
#define V vector
using namespace std;
const int N = 2e5 + 7;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
const ll mod1 = 2 * mod - 2;

inline char nc() {
    static char buf[1000000], *p1 = buf, *p2 = buf;
    return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? EOF : *p1++;
}
template <typename _Tp> inline void read(_Tp&sum) {
    char ch = nc(); sum = 0;
    while (!(ch >= '0'&&ch <= '9')) ch = nc();
    while (ch >= '0'&&ch <= '9') sum = (sum << 3) + (sum << 1) + (ch - 48), ch = nc();
}

int n,m;
int a[N];
int mp[N];

ll ksm(ll x, ll y){
    ll p = 1;
    while(y){
        if(y & 1) p = p * x % mod;
        x = x * x % mod;
        y >>= 1;
    }
    return p;
}

void solve(){
    scanf("%d",&n);
    set<int>s;
    for(int i = 1; i <= n; i ++){
        scanf("%d",&a[i]);
        mp[a[i]]++,s.insert(a[i]);
    }
    ll ans = 1, sum = 1;
    for(int i : s){
        sum = sum * (mp[i] + 1) % mod1;
    }
    for(int i : s){
        ans = ans * ksm(1ll * i, sum * mp[i] / 2) % mod;
    }
    printf("%lld\n",ans);

}

int main()
{
#ifdef ONLINE_JUDGE
#else
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif

    int T = 1;
    // scanf("%d",&T);
    while(T--){
        solve();
    }
    return 0;
}
posted @ 2021-11-12 00:41  !^^!  阅读(50)  评论(0编辑  收藏  举报