Multipliers codeforces -費馬小定理

http://codeforces.com/contest/615/problem/D


Ayrat has number n, represented as it's prime factorization pi of size m, i.e. n = p1·p2·...·pm. Ayrat got secret information that that the product of all divisors of n taken modulo 109 + 7 is the password to the secret data base. Now he wants to calculate this value.

Input

The first line of the input contains a single integer m (1 ≤ m ≤ 200 000) — the number of primes in factorization of n.

The second line contains m primes numbers pi (2 ≤ pi ≤ 200 000).

Output

Print one integer — the product of all divisors of n modulo 109 + 7.

Sample test(s)
Input
2
2 3
Output
36
Input
3
2 3 2
Output
1728
Note

In the first sample n = 2·3 = 6. The divisors of 6 are 1, 2, 3 and 6, their product is equal to 1·2·3·6 = 36.

In the second sample 2·3·2 = 12. The divisors of 12 are 1, 2, 3, 4, 6 and 12. 1·2·3·4·6·12 = 1728.


題意:給n各質數,求這n各質數相乘的值m的所有的因子的乘積mod(1e9+7)。例如給出3個質數2,2,3。乘積爲12。讓求1×2×3×4×6×12mod(1e9+7)的值。

解題思路:

小於200000的素數不是很多,所以肯定有很多重複的數字。開一個map,記錄素數和對應的個數。

然後看組合情況,假設素數j有k個,那麼j有(kj+1)種出現的形式,所以對於所有的素數就有(k1+1)×(k2+1)×(k3+1)×(k4+1)*...*(kn+1)= sum種組合方式。不考慮j時就有sum/(kj+1)種。假設其中一種除j外的乘積爲a,那麼就有(a)×(a×j)×(a× j^2)×(a×j^3)×...×(a×j^kj) = (a^(kj+1))×(j^(kj*(kj+1)/2)) .所以在所有的情況中共乘了j^((kj*(kj+1)/2))^(sum/(kj+1)).對於每一個素數求解一遍,乘積mod(1e9+7)爲結果。

但是因爲數據量過大,會導致sum爆 long long,所以在求解每一個j的sum/(kj+1)時要想辦法。

我們用cnt(j)表示j^((kj*(kj+1)/2))

所以我們用d表示遍歷到j時的種類的個數,即d(j)= (k1+1)×(k2+1)×(k3+1)×...×(kj+1)

然後

d(0)=1;ans = 1;
for j in ma:
    cnt(j)
    ans=ans^(k+1)*cnt(j)^d(j-1);
    d(j)
ans爲最終結果

例如我們有一組數據2 2 3 5 5
cnt(1) = 2^(2*3/2)=8,cnt(2)=3^(1+2/2)cnt(3)
j = 1:
    ans = cnt(1)^1
    d(1)=d(0)*(k1+1)=(k1+1)
j = 2:
    ans = cnt(1)^1^(k2+1)*cnt(2)^(k1+1)
    d(2) =d(1)*(k2+1)= (k1+1)*(k2+1)
j = 3:
    ans = cnt(1)^1^(k2+1)^(k3+1)*cnt(2)^(k1+1)(k3+1)*cnt(3)^(k1+1)*(k2+1)
    d(3) = d(2)*(k3+1)

並且在本解法中沒有sum/k的運算。由費馬小定理若p是質數,且gcd(a,p)=1,那麼 a^(p-1)≡1(mod p),則a^x≡a^(x%(m-1))(mod p)
所以再加上%mod得到:
d(0)=1;ans = 1;
for j in ma:
    cnt(j)
    ans=ans^(k+1)%mod*cnt(j)^d(j-1)%mod;
    d(j)%(mod-1)
然後再用快速冪解法
ll fast_mod(ll n,ll m,ll mod){
	ll ans =1;
	while(m){
		if(m&1)ans = ans*n%mod;
		m>>=1;
		n = n*n%mod;
	}
	return ans;
}

即可快速的求解出ans。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll p[200050];
map<int ,ll>MA;
const ll mod = 1e9+7;
ll fast_mod(ll n,ll m,ll mod){
	ll ans =1;
	while(m){
		if(m&1)ans = ans*n%mod;
		m>>=1;
		n = n*n%mod;
	}
	return ans;
}
int main(){
	int T;
	cin>>T;
	MA.clear();
	for(int i = 0;i<T;i++){
		int a;
		scanf("%d",&a);
		MA[a]++;
	}
	map<int,ll>::iterator it;
	ll sum = 1;
	ll ans = 1;
	for(it = MA.begin();it!=MA.end();it++){
		int cnt = fast_mod(it->first,(it->second+1)*it->second/2,mod);
		ans=fast_mod(ans,it->second+1,mod)*fast_mod(cnt,sum,mod)%mod;
		sum=sum*(it->second+1)%(mod-1);
	}
	printf("%I64d\n",ans);
}
發佈了61 篇原創文章 · 獲贊 53 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章