Codeforces Round #589 (Div. 2) C.Primes and Multiplication (数学,质因子分解+快速幂)

设 x 的质因子为p1,p2,p3…
f(x,1) * f(x,2) *… * f(x,n)
= g(1,p1) * g(2,p1) * g(3,p1) * … * g(n,p1) *
g(1,p2) * g(2,p2) * g(3,p2) * … * g(n,p2) *
g(1,p3) * g(2,p3) * g(3,p3) * … * g(n,p3) * …
这样可以用每个质因子求出n项 g()的解。
g(y,p)=p^k (y% p^k==0的最大k)
对于 p1 来说, 能够整除p1的数字一共有 n/p1 个 ,整除 p1^2 的数字有 n/p1^2 个…依次类推,那么有 n/p1 项贡献 p1,答案 ans 乘以 p1^(n/p1) , 有 n/( p1^2 ) 项贡献 p1^2,答案 ans 乘以 p12^ (n/p1^2) ,以此类推… 。但是能够整除 p1^2的数字也必定能够整除 p1 ,能够整除p1^k 的数字必定能够整除 p1^t (0<t<k) ;
因此 ,我们需要进行去重。
可以这样考虑:
我们先把 n/p1 项的贡献 p1 乘到答案上, ans = ans * fp( p1 , n/p1 ) % mod; (fp 为快速幂)
当算n/ (p1^2) 时, 有 n/ (p1^2) 项 , 由于 在算贡献为 p1 时, 答案已经乘以了 这么多项p1,其中就包括 因子含有 p1 ^ 2 的数,所以只需要乘以 p1^ ( n/p1^2 ) 即可。

例如: 2 4 6 8 10 ,p1=2;
第一次 ,都能整除2,答案乘以 5个 2。
第二次, 4 和 8 能整除 2^2,但第一次的时候 4 8 对答案已经贡献了2,那么只需要再贡献2 就能变成 2^2 了。

依次类推

其实就相当于第一次操作把 2 4 6 8 10 变成了 1 2 3 4 5 ,第二次变成了 1 1 3 2 5 …把所有 数字的质因子 2 全部乘到答案上。

AC代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e3+5;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
LL read()
{
    LL x=0,t=1;
    char ch=getchar();
    while(!isdigit(ch)){ if(ch=='-')t=-1; ch=getchar(); }
    while(isdigit(ch)){ x=10*x+ch-'0'; ch=getchar(); }
    return x*t;
}
vector<LL> p;
vector<LL> sum;
LL fp(LL x,LL y)///快速幂
{
    LL res=1;
    while(y)
    {
        if(y&1) res=res*x%mod;
        x=x*x%mod;
        y>>=1;
    }
    return res;
}
void solve(LL n)///质因子分解
{
    p.clear();
    for(LL i=2; i*i<=n; i++)
    {
        if(n%i==0)
        {
            p.push_back(i);
            while(n%i==0) n/=i;
        }
    }
    if(n>1) p.push_back(n);
}
int main()
{
    LL x=read(),n=read();
    solve(x);
    LL ans=1;
    for(int i=0;i<p.size();i++)
    {
        LL t=n;
        while(t)
        {
            t/=p[i];
            ans=ans*fp(p[i],t)%mod;
        }
    }
    printf("%lld
",ans);
}
原文地址:https://www.cnblogs.com/DeepJay/p/12025201.html