- 设(x)为(n)个有标号元素的集合划分数目,求(m^x(mod 99999599))。
- (n,mle10^{18})
贝尔数及其性质
关于贝尔数可见这篇博客:浅谈贝尔数及其性质。
然后我们发现要求的(x)就是(B_n)。
题目中已经很良心地给出了(999999598=2 imes13 imes5281 imes7283),因此我们考虑分别求出在这四个质数模数意义下的答案,然后中国剩余定理合并。
模数变成了质数,就可以利用贝尔数(Touchard)同余的性质:
[B_{n+p}equiv B_n+B_{n+1}(mod p)\
B_{n+p^m}equiv mB_n+B_{n+1}(mod p)
]
因此,只要给(n)做一个(p)进制拆分,然后从低位往高位枚举,对于第(i)位要依次加上一个(n'_i)个(p^i)。
我们只要维护好当前的(B_{nsim n+p-1})即可。特殊地,利用(B_{n+p}equiv B_n+B_{n+1})的性质也可以直接求出(B_{n+p}),用于求出新的(B_{n+p-1})。
一个奇怪的常数问题,一开始我用贝尔数的递推式预处理结果(TLE)了,然后换用贝尔数是第二类斯特林数的和的性质预处理就过了?!
代码:(O(sum p^2logn))
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define V 7283
#define X 999999599
#define LL long long
using namespace std;
const int Pt=4,p[Pt]={2,13,5281,7283};
LL n,m;I int QP(RI x,RI y,CI p) {RI t=1;W(y) y&1&&(t=1LL*t*x%p),x=1LL*x*x%p,y>>=1;return t;}
int B[V+5],S[2][V+5];I void Init()//用第二类斯特林数和来预处理贝尔数
{
RI i,j,op;for(op=S[0][0]=B[0]=i=1;i<=V;op^=1,++i) for(S[op][0]=0,
j=1;j<=i;++j) S[op][j]=(1LL*j*S[op^1][j]+S[op^1][j-1])%(X-1),B[i]=(B[i]+S[op][j])%(X-1);
}
int v[60],b[V+5];I int Calc(CI P)//求解模数为P的答案
{
RI i,j,k,t=-1;LL x=n;W(x) v[++t]=x%P,x/=P;for(k=0;k<=P;++k) b[k]=B[k]%P;//P进制拆分
for(i=1;i<=t;++i) for(j=1;j<=v[i];++j) {for(k=0;k^P;++k) b[k]=(1LL*i*b[k]+b[k+1])%P;b[P]=(b[0]+b[1])%P;}//从低位往高位枚举,加上v[i]个p^i
return b[v[0]];//根据第0位的值返回答案
}
int main()
{
RI i,t=0,P=1;for(scanf("%lld%lld",&n,&m),Init(),i=0;i^Pt;++i)//枚举模数的每个质因子
t+=1LL*(Calc(p[i])-t%p[i]+p[i])*QP(P,p[i]-2,p[i])%p[i]*P,P*=p[i];//中国剩余定理合并
return printf("%d
",QP(m%X,t,X)),0;
}