ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

Description

Input

共一行包括两个正整数N和M。

Output

共一行为所求表达式的值对10^9+7取模的值。

特判m=1

m≠1时:

设S[u]=sigma(i^u*m^i)

m*S[u]=sigma(i^u*m^(i+1))

=sigma((i-1)^u*m^i)+n^u*m^(n+1)

两式相减得(m-1)*S[u]=n^u*m^(n+1)-sigma((i^u-(i-1)^u)*m^i)

S[u]=(n^u*m^(n+1)-sigma((i^u-(i-1)^u)*m^i))/(m-1)

i^u-(i-1)^u可以展开,从而由S[0..u-1]计算出S[u],预处理二项式系数(组合数)即可

边界条件S[0]=sigma(m^i)=(m^n-1)*m/(m-1)

除法要取逆元

时间复杂度为O(m2logn)

#include<cstdio>
typedef long long lint;
const int P=1000000007;
lint f[1024][1024];
lint s[1024];
bool d[1024];
int n,m;
lint power(lint x,lint t){
    lint v=1,c=x;
    while(t){
        if(t&1)v=v*c%P;
        c=c*c%P;
        t>>=1;
    }
    return v;
}
lint div(lint a,lint b){
    return a*power(b,P-2)%P;
}
lint S(int m1){
    if(d[m1])return s[m1];
    lint v=power(n,m1)*power(m,n+1)%P;
    for(int i=m1-1,j=-1;i>=0;i--,j=-j){
        lint r=S(i)*f[m1+1][i+1]*j;
        v+=r;
        v%=P;
    }
    v=div(v,m-1);
    d[m1]=1;
    return s[m1]=v;
}
int main(){
    scanf("%d%d",&n,&m);
    if(m==1){
        printf("%lld",n*1ll*(n+1)/2%P);
        return 0;
    }
    f[1][1]=1;
    d[0]=1;
    s[0]=div(power(m,n)-1,m-1)*m%P;
    for(int i=2;i<=m+1;i++){
        for(int j=1;j<=i;j++)f[i][j]=(f[i-1][j]+f[i-1][j-1])%P;
    }
    printf("%lld\n",(S(m)+P)%P);
    return 0;
}

 

posted on 2016-03-19 18:23  nul  阅读(489)  评论(0编辑  收藏  举报