题目链接:
题意:给出n。求n有多少种划分集合的方式,即bell(n)
思路:
#include <iostream>
#include <cstdio>#include <string.h>#include <algorithm>#include <cmath>#include <vector>#include <queue>#include <set>#include <stack>#include <string>#include <map>#define max(x,y) ((x)>(y)?(x):(y))#define min(x,y) ((x)<(y)?(x):(y))#define abs(x) ((x)>=0?(x):-(x))#define i64 long long#define u32 unsigned int#define u64 unsigned long long#define clr(x,y) memset(x,y,sizeof(x))#define CLR(x) x.clear()#define ph(x) push(x)#define pb(x) push_back(x)#define Len(x) x.length()#define SZ(x) x.size()#define PI acos(-1.0)#define sqr(x) ((x)*(x))#define MP(x,y) make_pair(x,y)#define FOR0(i,x) for(i=0;i<x;i++)#define FOR1(i,x) for(i=1;i<=x;i++)#define FOR(i,a,b) for(i=a;i<=b;i++)#define DOW0(i,x) for(i=x;i>=0;i--)#define DOW1(i,x) for(i=x;i>=1;i--)#define DOW(i,a,b) for(i=a;i>=b;i--)#define rush() int CC;for(scanf("%d",&CC);CC--;)#define Rush(n) while(scanf("%d",&n)!=-1)using namespace std;void RD(int &x){scanf("%d",&x);}void RD(i64 &x){scanf("%lld",&x);}void RD(u32 &x){scanf("%u",&x);}void RD(double &x){scanf("%lf",&x);}void RD(int &x,int &y){scanf("%d%d",&x,&y);}void RD(i64 &x,i64 &y){scanf("%lld%lld",&x,&y);}void RD(u32 &x,u32 &y){scanf("%u%u",&x,&y);}void RD(double &x,double &y){scanf("%lf%lf",&x,&y);}void RD(int &x,int &y,int &z){scanf("%d%d%d",&x,&y,&z);}void RD(i64 &x,i64 &y,i64 &z){scanf("%lld%lld%lld",&x,&y,&z);}void RD(u32 &x,u32 &y,u32 &z){scanf("%u%u%u",&x,&y,&z);}void RD(double &x,double &y,double &z){scanf("%lf%lf%lf",&x,&y,&z);}void RD(char &x){x=getchar();}void RD(char *s){scanf("%s",s);}void RD(string &s){cin>>s;}void PR(int x) {printf("%d\n",x);}void PR(i64 x) {printf("%I64d\n",x);}void PR(u32 x) {printf("%u\n",x);}void PR(u64 x) {printf("%llu\n",x);}void PR(double x) {printf("%.3lf\n",x);}void PR(char x) {printf("%c\n",x);}void PR(char *x) {printf("%s\n",x);}void PR(string x) {cout<<x<<endl;}const i64 inf=((i64)1)<<60;const double dinf=1e10;const int INF=2000000000;const int N=100005;int a[]={31,37,41,43,47};i64 C[105][105],B[105];int n;i64 exGcd(i64 a,i64 b,i64 &x,i64 &y){ i64 t,d; if(!b) { x=1; y=0; return a; } d=exGcd(b,a%b,x,y); t=x; x=y; y=t-a/b*y; return d;}int modular1(i64 a[],i64 m[],int k){ i64 d,t,c,x,y,i; for(i=2;i<=k;i++) { d=exGcd(m[1],m[i],x,y); c=a[i]-a[1]; if(c%d) return 0; t=m[i]/d; x=(c/d*x%t+t)%t; a[1]=m[1]*x+a[1]; m[1]=m[1]*m[i]/d; } return 1;}int M,mod;struct Matrix{ i64 a[50][50]; void init(int x) { clr(a,0); int i; if(x) FOR0(i,50) a[i][i]=1; } Matrix operator*(Matrix p) { Matrix ans; ans.init(0); int i,j,k; FOR0(k,M) FOR0(i,M) FOR0(j,M) { ans.a[i][j]+=a[i][k]*p.a[k][j]%mod; ans.a[i][j]%=mod; } return ans; } Matrix pow(int n) { Matrix ans,p=*this; ans.init(1); while(n) { if(n&1) ans=ans*p; p=p*p; n>>=1; } return ans; }};Matrix q;i64 cal(i64 p){ int i,j; for(i=1;i<=p;i++) { C[i][0]=C[i][i]=1; for(j=1;j<i;j++) C[i][j]=(C[i-1][j]+C[i-1][j-1])%p; } B[0]=B[1]=1; for(i=2;i<=p;i++) { B[i]=0; for(j=0;j<i;j++) B[i]=(B[i]+C[i-1][j]*B[j]%p)%p; } if(n<=p) return B[n]; q.init(0); M=p; mod=p; for(i=1;i<p;i++) q.a[i][i-1]=1; q.a[0][p-1]=q.a[1][p-1]=1; q=q.pow(n-p+1); i64 ans=0; FOR0(i,p) ans=(ans+B[i]*q.a[i][p-1])%p; return ans;}int main(){ rush() { RD(n); i64 A[10],M[10],i; FOR0(i,5) M[i+1]=a[i],A[i+1]=cal(a[i]); modular1(A,M,5); printf("%I64d\n",A[1]); } return 0;}