C.Anadi and Domino
题意
给定
x
,
n
x,n
x,n,求
∏
i
=
1
n
f
(
x
,
i
)
\displaystyle\prod_{i=1}^{n}f(x,i)
i=1∏nf(x,i)
定义1: 对于
g
(
x
,
p
)
g(x,p)
g(x,p),定义
k
k
k 是
x
x
x 可以整除
p
p
p 的最大次幂,那么
g
(
x
,
p
)
=
p
k
g(x,p)=p^k
g(x,p)=pk
例如
g
(
45
,
3
)
=
9
g(45,3)=9
g(45,3)=9,
3
2
3^2
32可以整除
45
45
45,但是
3
3
3^3
33就不可以整除
45
45
45,所以
k
=
2
,
g
(
45
,
3
)
=
3
2
=
9
k = 2,g(45,3)=3^2=9
k=2,g(45,3)=32=9
定义2: f ( x , y ) = ∏ p g ( y , p ) [ p 是 x 的 质 因 子 ] \displaystyle f(x,y) =\prod_{p}g(y,p)[p是x的质因子] f(x,y)=p∏g(y,p)[p是x的质因子]
思路
现将
x
x
x 用试除法分解质因子,然后根据一个推论:
[1,n] 中因子中含有 i 的数字个数是
⌊
n
i
⌋
\displaystyle\lfloor\frac{n}{i}\rfloor
⌊in⌋
在kuangbin的练习中(J)也用过这个推论。
找出所有的然后每次累乘 qpow(p[i],n / p[i]),在乘的过程中取余即可。(qpow是快速幂)
下面以 x = 12 , n = 11 x=12,n = 11 x=12,n=11来举例:
先打出所有的
f
(
x
,
i
)
,
i
<
=
n
f(x,i),i <= n
f(x,i),i<=n,分解
12
12
12 是
2
2
3
2^2\ 3
22 3
先将
[
1
,
11
]
[1,11]
[1,11] 中因子有
2
2
2的数字 中的
2
2
2先提出来乘,
2
,
4
,
6
,
8
,
10
2,4,6,8,10
2,4,6,8,10一共
5
5
5个数 ,就乘上
2
5
2^5
25,
这样上图就变成这样
灰色代表我们已经乘过了
之后将
11
/
2
11\ / \ 2
11 / 2(整除),得到
5
5
5,再找
[
1
,
5
]
[1,5]
[1,5]中 因子有
2
2
2的数字,是
2
,
4
2,4
2,4一共
2
2
2个数,乘上
2
2
2^2
22。
这一步相当于把第二张图中,第
4
4
4 项和第
8
8
8 项的
2
2
2 也给乘掉。
这样所有的
2
2
2就都乘完了
之后的质因子就都是这样乘,这种方法有点埃式筛法的意思。
#include<bits/stdc++.h>
#define ll __int64
using namespace std;
const int N = 1e5 + 7;
const int mod = 1e9 + 7;
int c[N],p[N],tot = 0;
int prime[N],prime_tot = 0;
bool prime_tag[N];
ll x,n;
void get_prime(){
for(ll i = 2; i < N; i++) prime_tag[i] = true;
for(ll i = 2; i < N; i++){
for(ll j = i * i ; j < N; j += i)
prime_tag[j] = false;
}
for(int i = 2; i < N; i++)
if(prime_tag[i]) prime[prime_tot++] = i;
}
ll qpow(ll a,ll b){
ll res = 1;
while(b){
if(b & 1){
res = res * a % mod;
}
a = a * a % mod;
b >>= 1;
}
return res;
}
void divide(ll n) {
for(int i = 0 ; i < prime_tot && prime[i]*prime[i] <= n; i++) {
if(n % prime[i] == 0) {
p[++tot] = prime[i];
while(n % prime[i] == 0 && n > 1) {
c[tot]++;
n /= prime[i];
}
if(n == 1) break;
}
}
if(n > 1) {
p[++tot] = n;
c[tot] = 1;
}
}
ll solve(ll m){
ll res = 1,t;
divide(x);
for(int i = 1 ; i <= tot; i++){
t = m;
while(t){
res = res % mod * qpow(p[i],t / p[i]) % mod;
t /= p[i];
//printf("res = %I64d \n",res);
}
}
return res;
}
int main(){
ll ans;
get_prime();
scanf("%I64d%I64d",&x,&n);
ans = solve(n);
printf("%I64d",ans);
return 0;
}