Hdu4767 Bell (贝尔数 中国剩余定理 构造矩阵)
来源:互联网 发布:vb.net 鼠标穿透控件 编辑:程序博客网 时间:2024/04/25 20:27
2013年长春网络赛的题。
比赛时很快就找到了bell数的性质,看到数据范围也马上想到要用矩阵做,只可惜当时没接触过中国剩余定理……
以下题解转自:http://fudq.blog.163.com/blog/static/19135023820139114642927
对于贝尔数,如果p是任意质数,则有B[p+n]=B[n]+B(n+1)%p
还有可以发现的是95041567=31*37*41*43*47。
利用以上信息我们便可解此题。
如果能够得到B(n)%31,B(n)%37,B(n)%41,B(n)%43,B(n)%47的结果,我们便可以用中国剩余定理求出B(n)%95041567的结果
现在问题转换成求B(n)%w[i],由于w[i]是质数,便可利用上面Bell数的性质。
举个例子,如果w[i]=5,可以由B0 B1 B2 B3 B4得到B5 B6 B7 B8,又由B4 B5 B6 B7 B8得到B9 B10 B11 B12,依次类推。
这时可以利用矩阵二次幂快速求解,构造一个如下所示的01矩阵:
0 1 0 0 0
0 1 1 0 0
0 0 1 1 0
0 0 0 1 1
1 0 0 0 1
便可以由B0 B1 B2 B3 B4得到B4 B5 B6 B7 B8。
对于一个n,需要将构造矩阵乘上n/(w[i]-1)次,第n%(w[i]-1)列的结果便是B(n)%w[i]。
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N=55;int stir2[5][N][N]; //第二类斯特林数int bell[5][N]; //贝尔数int data[5];int mod[] = {31, 37, 41, 43, 47};int modd; //矩阵计算时的模值class Matrix{public:int a[N][N];int n; //矩阵大小void init (int x){memset(a,0,sizeof(a));if (x) for (int i=0;i<N;i++)a[i][i]=1; }Matrix operator * (Matrix b){Matrix p;p.n=b.n; //p.init(0);for (int i=0;i<n;i++) for (int j=0;j<n;j++)for (int k=0;k<n;k++)(p.a[i][j]+=a[i][k]*b.a[k][j]%modd)%=modd;return p;}Matrix power (int t){Matrix ans,p=*this;ans.n=p.n; //ans.init(1);while (t){if (t&1) ans=ans*p;p=p*p;t>>=1;}return ans;}}a;void Init () //预处理50以下的贝尔数{ int i,j,k; for (i=0;i<5;i++) { stir2[i][0][0]=1; bell[i][0]=bell[i][1]=1; } for (i=1;i<=50;i++) { for (j=0;j<5;j++) stir2[j][i][1]=stir2[j][i][i]=1; for (j=1;j<=i;j++) for (k=0;k<5;k++) stir2[k][i][j]=(stir2[k][i-1][j-1]+j*stir2[k][i-1][j])%mod[k]; } for (i=1;i<=50;i++) for (k=0;k<5;k++) { bell[k][i]=0; for (j=0;j<=i;j++) bell[k][i]=(bell[k][i]+stir2[k][i][j])%mod[k]; }}int Extended_Euclid (int a,int b,int &x,int &y){//扩展欧几里得算法,求ax+by=gcd(a,b)的一组解(x,y),d=gcd(a,b)int d;if (b==0){x=1;y=0;return a;}d=Extended_Euclid(b,a%b,y,x);y-=a/b*x;return d;}int Chinese_Remainder (int a[],int w[],int len){//中国剩余定理 a[]存放余数 w[]存放两两互质的数int x,y,m;int lcm=1,i,ans=0;for (i=0;i<len;i++)lcm*=w[i];for (i=0;i<len;i++){m=lcm/w[i];Extended_Euclid(w[i],m,x,y);ans=(ans+y*m*a[i])%lcm;}return (lcm+ans%lcm)%lcm;}int Cal (int n,int t)//构造矩阵a,计算bell[n]%w[t]{int ans=0,i;a.init(0);a.n=mod[t];modd=mod[t];for (i=1;i<mod[t];i++)a.a[i][i]=a.a[i-1][i]=1;a.a[ mod[t]-1 ][0]=1;int p1=n/(mod[t]-1);int p2=n%(mod[t]-1);a=a.power(p1);for (i=0;i<mod[t];i++)ans=(ans+bell[t][i]*a.a[i][p2])%mod[t];return ans;}int main (){#ifdef ONLINE_JUDGE#elsefreopen("read.txt","r",stdin);#endif int T,n,i; scanf("%d",&T); Init (); while (T--) { scanf("%d",&n); if (n<50) { for (i=0;i<5;i++) data[i]=bell[i][n]; printf("%d\n",Chinese_Remainder(data,mod,5)); continue; } for (i=0;i<5;i++) data[i]=Cal(n,i); printf("%d\n",Chinese_Remainder(data,mod,5)); }return 0;}
- Hdu4767 Bell (贝尔数 中国剩余定理 构造矩阵)
- 贝尔数 hdu4767 (矩阵快速幂+中国剩余定理+bell数+Stirling数+欧几里德)
- HDU4767 Bell 中国剩余定理 贝尔数 第二类斯特灵数
- Bell(hdu4767+矩阵+中国剩余定理)
- HDU 4767 Bell (贝尔数 中国剩余定理 构造矩阵) ★ ★
- Bell数+中国剩余定理
- hdu 4767 bell 中国剩余定理+矩阵快速幂
- Bell(矩阵快速幂+中国剩余定理)
- HDU 4767 Bell (中国剩余定理)
- HDU 4767 Bell (中国剩余定理)
- hdu 4746 Bell 中国剩余定理+矩阵乘法+第二类斯特林数 (2013网络赛)
- 贝尔(Bell)数
- HDU4767(待做)&&HDU2512 【Bell数】
- 中国剩余定理-数硬币
- Bell - HDU 4767 贝尔数
- 中国剩余定理模版【中国剩余定理】
- 中国剩余定理:从构造特解到找出通解
- 中国剩余定理
- android系统图标的使用
- 程序员没用过Beyond Compare?你out了
- cocos2d-x精灵的放大和缩小
- format string使用例子
- linux内核-信号
- Hdu4767 Bell (贝尔数 中国剩余定理 构造矩阵)
- Unity3D--day03
- c/c++(一) 一种我个人不太长见的C++函数名指针化写法
- JavaScript入门
- 坠落凡间的struts2(6)---文件的上传下载
- 使IRB语法高亮方法的办法
- zip, tar, tar.gz, tar.bz2, jar,7z等格式文件的压缩和解压方法
- JAVA泛型类和泛型方法
- 500 OOPS: cannot change directory:/root 问题