• BZOJ 2627 JZPKIL


    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2627

    题意:计算下面式子

    思路:

    A先不管。我们来搞B部分。下面说如何计算B这个最后那部分

    伯努利函数:

    所以

    带入到B中

    那个f(k)中k一旦确定x,y,k就是常数,所以就是关于n的函数。

    因为d^x以及莫比乌斯函数都是积性函数,而g是他们的狄利克雷卷积,所以g也是积性函数。所以依次计算每个n的质因子即可。

    这样我们计算每个质因数即可。现在我们计算g(ps)

    我们发现

    所以

    这样我们就计算出上面的B,即

    那么还剩A,我们发现A=f(1)。

    这样就全部搞定。这道题涉及组合数、伯努利数以及大素数的判定分解。

    const i64 mod=1000000007;
    const int N=3005;
     
     
    i64 exGcd(i64 a,i64 b,i64 &x,i64 &y)
    {
        i64 r,t;
        if(b==0)
       {
           x=1;
           y=0;
           return a;
       }
       r=exGcd(b,a%b,x,y);
       t=x;
       x=y;
       y=t-a/b*y;
       return r;
    }
     
    i64 reverse(i64 a,i64 b)
    {
        i64 x,y;
        exGcd(a,b,x,y);
        if(x<0) x+=mod;
        return x;
    }
     
     
    int C[N][N],p[N],pInv[N],B[N],T[N][N];
    int prime[N],primeNum,tag[N];
     
    void init()
    {
        p[0]=pInv[0]=1;
        for(int i=1;i<N;i++)
        {
            p[i]=(i64)p[i-1]*i%mod;
            pInv[i]=reverse(p[i],mod);
        }
        C[0][0]=1;
        for(int i=1;i<N;i++)
        {
            C[i][0]=C[i][i]=1;
            for(int j=1;j<i;j++)
            {
                C[i][j]=C[i-1][j-1]+C[i-1][j];
                if(C[i][j]>=mod) C[i][j]-=mod;
            }
        }
        B[0]=1;
        for(int i=1;i<N;i++)
        {
            B[i]=0;
            for(int j=0;j<i;j++)
            {
                B[i]-=(i64)C[i+1][j]*B[j]%mod;
                if(B[i]<0) B[i]+=mod;
            }
            B[i]=B[i]*reverse(C[i+1][i],mod)%mod;
        }
        for(int i=0;i<N;i++)
        {
            i64 a=reverse(i+1,mod);
            for(int j=0;j<=i;j++)
            {
                T[i][j]=a*B[j]%mod*C[i+1][j]%mod;
            }
        }
        for(int i=2;i<N;i++) if(!tag[i])
        {
            prime[primeNum++]=i;
            for(int j=i+i;j<N;j+=i) tag[j]=1;
        }
    }
     
    i64 Gcd(i64 x,i64 y)
    {
        if(!y) return x;
        return Gcd(y,x%y);
    }
     
    i64 mul(i64 x,i64 y,i64 mod)
    {
        i64 ans=0;
        while(y)
        {
            if(y&1)
            {
                ans+=x;
                if(ans>=mod) ans-=mod;
            }
            x<<=1;
            if(x>=mod) x-=mod;
            y>>=1;
        }
        return ans;
    }
     
     
    i64 myPow(i64 a,i64 b,i64 mod)
    {
        i64 ans=1;
        while(b)
        {
            if(b&1) ans=mul(ans,a,mod);
            a=mul(a,a,mod);
            b>>=1;
        }
        return ans;
    }
     
    i64 myPow(i64 a,i64 b)
    {
        a%=mod;
        i64 ans=1;
        while(b)
        {
            if(b&1)
            {
                ans*=a;
                if(ans>=mod) ans%=mod;
            }
            a*=a;
            if(a>=mod) a%=mod;
            b>>=1;
        }
        return ans;
    }
     
    void cal1(i64 n,int x,int y)
    {
        if(0==x)
        {
            printf("%lld
    ",n%mod);
            return;
        }
        i64 ans=0,p=(n+1)%mod,tmp=p;
        for(int i=y;i>=0;i--)
        {
            ans+=T[y][i]*tmp;
            ans%=mod;
            tmp=tmp*p%mod;
        }
        ans=ans*myPow(n,y)%mod;
        if(ans<0) ans+=mod;
        printf("%lld
    ",ans);
    }
     
    i64 all[N];
    int allNum;
     
    int witness(i64 a,i64 n)
    {
        i64 m=n-1,x,y,k=0;
        while(!(m&1)) k++,m>>=1;
        x=myPow(a,m,n);
        while(k--)
        {
            y=mul(x,x,n);
            if(1==y&&x!=1&&x!=n-1) return 1;
            x=y;
        }
        return y!=1;
    }
     
    int isPrime(i64 n)
    {
        if(2==n) return 1;
        if(!(n&1)) return 0;
        if(1==n) return 0;
     
        int cnt=17;
        while(cnt--)
        {
            i64 a=rand()%(n-1)+1;
            if(witness(a,n)) return 0;
        }
        return 1;
    }
     
     
    i64 pollard(i64 n,int c)
    {
        i64 x=1,y=1,d,k=2,i=1;
        while(1)
        {
            x=mul(x,x,n)+c;
            d=Gcd(abs(y-x),n);
            if(d>1&&d<n) return d;
            if(y==x) return n;
            if(++i==k) y=x,k<<=1;
        }
    }
     
    void split(i64 n)
    {
        if(1==n) return;
        if(isPrime(n))
        {
            all[++allNum]=n;
            return;
        }
        i64 m=n;
        int c=1;
        while(m==n) m=pollard(m,++c);
        split(m);
        split(n/m);
    }
     
     
    struct node
    {
        int primeNum;
        i64 p[N];
        int num[N];
        i64 po[N];
    }A;
     
    i64 pw[100][100],pw1[100];
     
    i64 get(i64 i,int y)
    {
        i64 tmp=1;
        for(int j=1;j<=A.primeNum;j++)
        {
            i64 S1=0,S2=0;
            i64 a=myPow(A.p[j],y);
            i64 b=myPow(A.p[j],y+1-i);
            pw1[0]=1;
            for(int k=1;k<=A.num[j];k++)
            {
                pw1[k]=pw1[k-1]*b;
                if(pw1[k]>=mod) pw1[k]%=mod;
            }
            for(int k=0;k<=A.num[j];k++)
            {
                S1+=pw[j][k]*pw1[A.num[j]-k];
                if(S1>=mod) S1%=mod;
            }
            for(int k=0;k<A.num[j];k++)
            {
                S2+=pw[j][k]*pw1[A.num[j]-k-1]%mod*a;
                if(S2>=mod) S2%=mod;
            }
            S1-=S2;
            S1%=mod;
            if(S1<0) S1+=mod;
            tmp=tmp*S1;
            if(tmp>=mod) tmp%=mod;
            tmp=tmp*myPow(A.po[j],y);
            if(tmp>=mod) tmp%=mod;
        }
        return tmp;
    }
     
    void cal2(i64 n,int x,int y)
    {
        allNum=0;
        for(int i=0;i<primeNum;i++)
        {
            while(0==n%prime[i])
            {
                all[++allNum]=prime[i];
                n/=prime[i];
            }
        }
        if(n>1) split(n);
        sort(all+1,all+allNum+1);
        A.primeNum=1;
        A.p[1]=all[1];
        A.num[1]=1;
        A.po[1]=all[1];
        for(int i=2;i<=allNum;i++)
        {
            if(all[i]==all[i-1])
            {
                A.num[A.primeNum]++;
                A.po[A.primeNum]*=all[i];
            }
            else
            {
                A.primeNum++;
                A.p[A.primeNum]=all[i];
                A.num[A.primeNum]=1;
                A.po[A.primeNum]=all[i];
            }
        }
        for(int i=1;i<=A.primeNum;i++)
        {
            pw[i][0]=1;
            i64 a=myPow(A.p[i],x);
            for(int j=1;j<=A.num[i];j++)
            {
                pw[i][j]=pw[i][j-1]*a;
                if(pw[i][j]>=mod) pw[i][j]%=mod;
            }
        }
     
     
        i64 ans=0;
        for(int i=0;i<=y;i++)
        {
            ans+=get(i,y)*T[y][i];
            ans%=mod;
        }
        if(y>0) ans+=get(1,y),ans%=mod;
        if(ans<0) ans+=mod;
        printf("%lld
    ",ans);
    }
     
    int main()
    {
     
        init();
        int T=myInt();
        while(T--)
        {
            i64 n;
            int x,y;
            scanf("%lld%d%d",&n,&x,&y);
            if(x==y) cal1(n,x,y);
            else cal2(n,x,y);
        }
    }
    

      

  • 相关阅读:
    【数论】【快速幂】【扩展欧几里得】【BSGS算法】bzoj2242 [SDOI2011]计算器
    【数论】【ex-BSGS】poj3243 Clever Y
    【数论】【扩展欧几里得】hdu3579 Hello Kiki
    【CCpp程序设计2017】推箱子游戏
    【Miller-Rabin算法】
    【数论】nefu119 组合素数
    【数论】nefu118 n!后面有多少个0
    【树形dp】vijos P1180 选课
    【树形dp】Codeforces Round #405 (rated, Div. 1, based on VK Cup 2017 Round 1) B. Bear and Tree Jumps
    【树形dp】VK Cup 2012 Round 1 D. Distance in Tree
  • 原文地址:https://www.cnblogs.com/jianglangcaijin/p/4213884.html
Copyright © 2020-2023  润新知