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;
}
Code will change the world !