zoukankan      html  css  js  c++  java
  • 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);
    }
    
  • 相关阅读:
    STM32 USART整理说明(转)
    C++ 如何初始化静态类成员
    scp、sftp和ftps
    PostGIS介绍
    string.h和strings.h的区别
    linux编程中的段错误
    Linux中的man命令
    undefinded reference to 'pthread_create'问题
    多核编程框架
    与ComboBox有相似行为的下拉控件的实现
  • 原文地址:https://www.cnblogs.com/DeepJay/p/12025201.html
Copyright © 2011-2022 走看看