【2025.10.14NOIP】WYF的盒子
题目描述
WYF有一个精致的k维立方体盒子(2维为正方形,3维为正方体,以此类推)。这个盒子的边长为n,里面有一个边长为n-1的盒子,边长为n-1的盒子里面还有一个边长为n-2的盒子……最里面的盒子边长为m。现在WYF想知道这n-m+1个盒子的k维体积和模p的余数。
输入
输入共一行包含4个正整数k, n, m, p。
输出
输出共一行包含1个正整数,表示n-m+1个盒子的k维体积之和模p的余数。
样例输入 复制
输入1: 4 2 2 97 输入2: 1 100 1 10007
样例输出 复制
输出1: 16 【样例说明】 边长为2的4维立方体的4维体积为16。 输出2 5050
数据范围限制

思路
考虑n-m<=5000特判,否则利用伯努利数:
O(n^2)出解。
代码见下
#include<bits/stdc++.h>
using namespace std;
long long k,n,m,p,lk=0,f[5150][5150],b[5150],nn[5150],jx[5150],jx2[5150];
long long pow2(long long a1,long long b1,long long m1){
long long kk1=1;
a1%=p;
while(b1>=1){
if(b1%2==1){
kk1=kk1*a1%p;
}
b1/=2;
a1=a1*a1%p;
}
if(a1==0){
kk1=0;
}
return kk1;
}
long long bnl2(long long a1,long long b1){
long long op=0;
for(int i=0;i<=b1;i++){
op=(op+pow2(a1,b1-i,p)*b[i]%p*f[b1][i]%p)%p;
}
op=(op+p)%p;
//cout<<op<<endl;
return op;
}
long long bnl(long long a1,long long b1){
long long op=0;
for(int i=0;i<=b1;i++){
op=(op+pow2(a1,b1+1-i,p)*b[i]%p*f[b1+1][i]%p)%p;
//cout<<pow2(a1,b1+1-i,p)<<" "<<b[i]<<" "<<f[b1+1][i]<<endl;
}
op=(op+p)%p;
op=nn[b1+1]*op%p;
//cout<<nn[0]<<endl;
return op;
}
int main(){
cin>>k>>n>>m>>p;
if(n-m<=6000){
lk=0;
for(int i=m;i<=n;i++){
lk=(lk+pow2(i,k,p))%p;
}
cout<<lk<<endl;
}
else{
for(int i=0;i<=5000;i++){
f[i][0]=1;
}
for(int i=0;i<=5000;i++){
f[i][i]=1;
}
for(int i=0;i<=5000;i++){
for(int j=1;j<=i;j++){
f[i][j]=(f[i-1][j-1]+f[i-1][j])%p;
}
}
for(int i=1;i<=5000;i++){
nn[i]=pow2(i,p-2,p);
}
b[0]=1;
for(int i=1;i<=5000;i++){
for(int j=0;j<=i-1;j++){
b[i]=(b[i]+b[j]*f[i+1][j])%p;
}
b[i]=(-nn[i+1]*b[i]%p)%p;
//cout<<b[i]<<endl;
}
b[1]=-b[1];
cout<<(bnl(n,k)-bnl(m-1,k)+p)%p<<endl;
}
return 0;
}

浙公网安备 33010602011771号