【jzoj4220】【五校联考2day2】【WYF的盒子】【自然数幂和】

题目大意

WYF有一个精致的k维立方体盒子(2维为正方形,3维为正方体,以此类推)。这个盒子的边长为n,里面有一个边长为n-1的盒子,边长为n-1的盒子里面还有一个边长为n-2的盒子……最里面的盒子边长为m。现在WYF想知道这n-m+1个盒子的k维体积和模p的余数。

解题思路

ans=ni=mik%p

ni=0ik=ki=1s(k,i)(n+1)(i+1)(线)/(i+1)

求出第二类斯特林数即可k^2求解,由于是任意模数不一定有逆元,而连续i+1个数一定有一个是i+1的倍数,这样就不用乘法了。对于模数过大,把一个数拆成两个较小的数相乘取模即可。

code

#include
#include
#include
#include
#define LF double
#define LL long long
#define ULL unsigned LL
#define fo(i,j,k) for(LL i=j;i<=k;i++)
#define fd(i,j,k) for(LL i=j;i>=k;i--)
#define fr(i,j) for(LL i=begin[j];i;i=next[i])
using namespace std;
LL max(LL x,LL y){return (x>y)?x:y;}
LL min(LL x,LL y){return (x<y)?x:y;}
LL const mk=2000+9,inf=1e9+7;
LL n,m,K,p,s[mk][mk];
LL mod(LL x,LL y){
    LL bit=1e6,a1=x/bit,a2=x%bit,b1=y/bit,b2=y%bit;
    LL tmp=(a1*b1%p*bit%p*bit%p+a1*b2%p*bit%p+b1*a2%p*bit%p+a2*b2%p)%p;
    return (a1*b1%p*bit%p*bit%p+a1*b2%p*bit%p+b1*a2%p*bit%p+a2*b2%p)%p;
}
LL calc(LL n){
    LL ans=0;
    fo(i,0,K){
        LL tmp=s[K][i];
        fd(j,n+1,n+1-i)
            tmp=mod(tmp,(j%(i+1)==0)?j/(i+1):j);
        ans=(ans+tmp)%p;
    }
    return ans;
}
LL pow(LL x,LL y){
    LL z=1;
    while(y){
        if(y&1)z=mod(z,x);
        x=mod(x,x);
        y>>=1;
    }
    return z;
}
int main(){
    freopen("d.in","r",stdin);
    freopen("d.out","w",stdout);
    scanf("%lld%lld%lld%lld",&K,&n,&m,&p);
    if(K>2000){
        LL ans=0;
        fo(i,m,n)
            ans=(ans+pow(i,K))%p;
        printf("%lld",ans);
        return 0;
    }
    s[0][0]=1;
    fo(i,1,K)fo(j,1,i)s[i][j]=(s[i-1][j-1]+j*s[i-1][j])%p;
    LL tmp=calc(n),tm2=calc(m-1);
    printf("%lld",((tmp-tm2)%p+p)%p);
    return 0;
}

你可能感兴趣的:(jzoj,数论)