昨天比赛被虐的这个题目。
今天听斌牛讲过他的思路后就A掉了。
题目的意思是要你求出bell数的第n项对95041567取模。
首先,95041567=31*37*41*43*47;
然后取模就是先分别取模,然后就用中国剩余定理合并了。
现在的问题就是如何求出来B[n]对95041567分别取模的结果了哦。
不错,现在你缺少的就是一个公式——B[P^m+n]==(B[n]+B[n+1])%P——P为任一个质数(来自维基百科)。
这样的话我们就可以递推了哦。
从大的开始往小的递推,每次减去一个最大的P^m,知道推到一个n<=P,用记忆化<map>就A掉了。
代码如下:
#include <iostream> #include <cstdio> #include <cstring> #include <map> #define N 95041567 #define maxn 2147483647 #define ll long long using namespace std; llm[5]={31,37,41,43,47},a[5],n,t; llf[5][50][50]; map<ll,ll>ss; void function() { for (lli=0; i<5; i++) { f[i][0][0]=1; f[i][1][1]=1; for (llj=2; j<=m[i]; j++) { f[i][j][1]=f[i][j-1][j-1]; for (llk=2; k<=j; k++) f[i][j][k]=(f[i][j][k-1]+f[i][j-1][k-1])%m[i]; } } } llget(lltot,llx) { if (tot<=m[x]) return f[x][tot][tot]; if (ss[tot]!=0) return ss[tot]; llM=1,cur=m[x]; while (cur*m[x]<=tot) M++,cur*=m[x]; ss[tot]=(M*get(tot-cur,x)+get(tot-cur+1,x))%m[x]; return ss[tot]; } void exgcd(llA,llB,ll& x,ll& y) { if (!B) { x=1,y=0; } else { exgcd(B,A%B,y,x); y-=A/B*x; } } llchina() { lld,x=0,y; for (lli=0; i<5; i++) { llw=N/m[i]; exgcd(m[i],w,d,y); x=(x+y*w*a[i])%N; } return (x+N)%N; } int main() { function(); cin>>t; while (t--) { cin>>n; for (lli=0; i<5; i++) { ss.clear(); a[i]=get(n,i); } cout<<china()<<" "; } return 0; }