题意不再叙述,链接如下
Primes and Multiplication
首先说一下思路,我们正常模拟,这道题非常的绕,其实就是,先给出两个数,x和n,从f(x,1)乘到f(x,n)再模1e9+7,求这个值
正常模拟,发现从1乘到n,n为1e18,O(n)算法一定超时,所以不能遍历n,只能去遍历x,
那么怎么个遍历x的方法,我们在普通模拟的时候发现,最后只是不断计算g(y,p)的值,代表y/pk为整数的最大值,p为x的质因数,所有质因数都用代入,y为从1到n,那我就只需要找从1到n每个质因数用到了多少次方即可,(因为y不能整除p的情况下,就会乘1,把1略去,就是只找质因数的倍数,就是1到n中整除p的次方数)
找法很关键
涉及到一个这样的代码
for(it = s.begin();it != s.end();it ++){
//遍历nTLE,遍历x
temp = n;
power = 0;
while(temp){
temp /= *it;
power += temp;
//算出有几个使用了该质数
}
ans = ans * fastpow(*it,power) % mod;
}
原理如下: x / p 得到的是x中有多少个数含有p这个公因数,而这一步之后的x代表将这些数全部都削减p倍,其中一开始只有p的一次方的数,此次就不算数了,然后继续让x /p,这次是得到,有多少个数含有p2这个因数,以此类推,就可以得到从1到n所有数含有多少个p次方
完整代码如下
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<iomanip>
#include<string>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<stack>
#include<utility>
#define PI acos(-1.0)
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
ll x,n;
ll fastpow(ll base, ll p){
ll res = 1;
while(p > 0){
if(p & 1) res = res * base % mod;
p >>= 1;
base = base * base % mod;
}
return res % mod;
}
int main(){
cin >> x >> n;
set<int> s;
set<int> :: iterator it;
for(int i = 2;i * i <= x; i ++){
if(x % i == 0){
s.insert(i);
while(x % i == 0){
x /= i;
}
}
}
if(x > 1) s.insert(x);
//欧拉函数原理
//此处注意埃氏筛,埃氏筛使用来打表,对持续使用质数的一段进行打表使用,不断地将一个数的倍数剔除
//而欧拉函数均可,我们可以使用欧拉函数对一个数进行求解其质因数
ll temp,power;
ll ans = 1;
for(it = s.begin();it != s.end();it ++){
//遍历nTLE,遍历x
temp = n;
power = 0;
while(temp){
temp /= *it;
power += temp;
//算出有几个使用了该质数
}
ans = ans * fastpow(*it,power) % mod;
}
cout << ans << endl;
return 0;
}