codeforces 1228 C 数论

原题链接

Let’s introduce some definitions that will be needed later.

Let prime(x) be the set of prime divisors of x. For example, prime(140)={2,5,7}, prime(169)={13}.

Let g(x,p) be the maximum possible integer pk where k is an integer such that x is divisible by pk. For example:

g(45,3)=9 (45 is divisible by 32=9 but not divisible by 33=27),
g(63,7)=7 (63 is divisible by 71=7 but not divisible by 72=49).
Let f(x,y) be the product of g(y,p) for all p in prime(x). For example:

f(30,70)=g(70,2)⋅g(70,3)⋅g(70,5)=21⋅30⋅51=10,
f(525,63)=g(63,3)⋅g(63,5)⋅g(63,7)=32⋅50⋅71=63.
You have integers x and n. Calculate f(x,1)⋅f(x,2)⋅…⋅f(x,n)mod(109+7).

Input
The only line contains integers x and n (2≤x≤109, 1≤n≤1018) — the numbers used in formula.
Output
Print the answer.

inputCopy
10 2
outputCopy
2

inputCopy
20190929 1605
outputCopy
363165664

inputCopy
947 987654321987654321
outputCopy
593574252

Note
In the first example, f(10,1)=g(1,2)⋅g(1,5)=1, f(10,2)=g(2,2)⋅g(2,5)=2.
In the second example, actual value of formula is approximately 1.597⋅10171. Make sure you print the answer modulo (109+7).
In the third example, be careful about overflow issue.

题意

prime(x):x的所有素因子
g(x,p):使p^k尽可能的大,同时满足x%p ^ k=0,最大的p ^ k就是g(x,p)的值
f(x,y):g(y,x1) * g(y,x2) * …*g(y,xn).(x1…xn为x的素因子)
给定x和n,求f(x,1) * f(x,2) * …f(x,n)的值

思路

对于数论这种题,我一般都是先推公式,然后再想用到哪些方法

1.我们举个例子,设x=6,n=6; prime(x)=2,3
2.然后模拟式子,f(x,1) * f(x,2) * f(x,3) * f(x,4) * f(x,5) * f(x,6)
3.继续推:g(1,2)*g(1,3) * g(2,2)*g(2,3) * g(3,2)*g(3,3) * g(4,2)*g(4,3) * g(5,2)*g(5,3) * g(6,2)*g(3,3)
4.继续化简:(第一部分) g(1,2)*g(2,2)*g(3,2)*g(4,2)*g(5,2)*g(6,2)
5.继续化简:(第二部分) g(1,3)*g(2,3)*g(3,3)*g(4,3) * g(5,3)*g(6,3)
6.到现在就全部化简完成了,那么我们看g(x,y)函数,就是表示y^k 最大且 x%y ^ k==0 进而我们可以知道,其实就是g(x,p)可以转化为p ^ k,而k可以看成p作为质因子在x中出现的次数。
7.现在问题基本解决,基本算法:快速幂,试除法分解因数

代码中有一块地方不好理解,额外解释一下
4.5两步如何求解

普通求解:直接暴力1-n,求出每个的幂,然后相加,但是会超时
转化思维:g(x,p) p是x的质因子,只有x是p的倍数才能取余等于0

具体模拟:g(1,2)*g(2,2)*g(3,2)*g(4,2)*g(5,2)*g(6,2)这个式子中,g(2,2) 贡献1次幂, g(4,2)贡献2次幂,g(6,2)贡献1次幂 ,所以sum=1+2+1=4;然后用快速幂求的24=16
代码实现:因为只有是倍数才会出现,所以6/2=3; 2的1倍,2的2倍,2的3倍,之后剩余3 ,3/2=1 ,这2的1倍 贡献为4

//遍历每一个质因子
for(int i=0;i<cnt;i++){
        ll s=n;
        ll sum=0;
        //求质因子的幂
        while (s){
            s/=primes[i];
            sum+=s;
        }
        res=(res*qmi(primes[i],sum))%mod;
    }

AC代码

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int mod = 1e9 + 7;

ll x, n;
ll primes[100001];
ll cnt;

//试除法求除x的所有质因子
void divide(int x){
    for(int i=2;i<=x/i;i++){
        if(x%i==0){
           primes[cnt++]=i;
           while(x%i==0){
               x/=i;
           }
        }
    }
    if(x>1)  primes[cnt++]=x;
}

//快速幂模板
ll qmi(ll m,ll k){
    ll res=1l;
    while (k){
        if(k&1) res=res*m%mod;
        m=m*m%mod;
        k>>=1;
    }
    return res;
}

int main() {

    cin >> x >> n;
    divide(x);
    ll res=1;
    for(int i=0;i<cnt;i++){
        ll s=n;
        ll sum=0;
        while (s){
            s/=primes[i];
            sum+=s;
        }
        res=(res*qmi(primes[i],sum))%mod;
    }
    cout<<res<<endl;

    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值