首页 > 代码库 > BZOJ 2627 JZPKIL

BZOJ 2627 JZPKIL

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

题意:计算下面式子

技术分享

思路:

技术分享

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

技术分享

伯努利函数:

技术分享

技术分享

所以

技术分享

带入到B中

技术分享

那个f(k)中k一旦确定x,y,k就是常数,所以就是关于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",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\n",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\n",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);    }}

  

 

BZOJ 2627 JZPKIL