• Bell(hdu4767+矩阵+中国剩余定理+bell数+Stirling数+欧几里德)


    Bell

    Time Limit:3000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u
     

    Description

    What? MMM is learning Combinatorics!? 
    Looks like she is playing with the bell sequence now: 
    bell[n] = number of ways to partition of the set {1, 2, 3, ..., n} 

    e.g. n = 3: 
    {1, 2, 3} 
    {1} {2 3} 
    {1, 2} {3} 
    {1, 3} {2} 
    {1} {2} {3} 
    so, bell[3] = 5 

    MMM wonders how to compute the bell sequence efficiently. 
     

    Input

    T -- number of cases 
    for each case: 
      n (1 <= n < 2^31) 
     

    Output

    for each case: 
      bell[n] % 95041567 
     

    Sample Input

    6
    1
    2
    3
    4
    5
    6
     

    Sample Output

    1
    2
    5
    15
    52
    203
     
     

    首先,我很高兴终于把这题给解出来了!!!自己有几个难点一直没想通,今天无聊的时候一想。然后思路莫名奇妙的顺了,一切都变的理所当然。。。然后,我趁热打铁,把思路一理,就被我A了!

    题意:就是求n个数的非空集合的划分方法数;

    例如n = 3

    {1, 2, 3}

    {1}  {2, 3}

    {1, 2} {3}

    {1, 3} {2}

    {1} {2} {3}

    所以Bell(3) = 5

    给你一个n,求Bell(n) % 95041567的值

    这道题涉及的知识比较多,,,本人觉得有一定的难度系数,没理解的,建议可以先从入门题刷起;

    思路:

      首先必须了解一个概念贝尔数(来自维基百科)& Stirling数(不懂的点链接);

      其次,如果你不懂Stirling数,那么自己动手推一下,其实这个还是简单的,杭电有一题简单的题,可以练习下:

      http://acm.hdu.edu.cn/showproblem.php?pid=2512 相信很多同学都做过了,只是当时不知道是Stirling数,这里是第二类Stirling数;然后贝尔数呢,就是第二类Stirling数的和;

    通过上面这个公式,我们可以利用矩阵计算大于n的贝尔数,方法是利用中国剩余定理,结合欧几里德和同余方程;首先我们输入n(假设,n>p,p是95041567的质因子,eg:n=50),对n<50的Bell数进行预处理,构造一个p*p的矩阵;

    利用公式求出,他们的余数存入数组at[i];质因子m[5]={31,37,41,43,47};利用中国剩余定理;求得余数!

    转载请注明出处:寻找&星空の孩子   

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4767

      1 #include<stdio.h>
      2 #include<string.h>
      3 #define LL long long
      4 #define mod 95041567
      5 #define MM 50
      6 
      7 int m[5]={31,37,41,43,47};
      8 int Sti[MM][MM],bell[MM][MM];
      9 int at[5];//各项余数
     10 
     11 void stirling2()
     12 {
     13     memset(Sti,0,sizeof(Sti));
     14     Sti[0][0]=1;
     15     for(int i=1;i<=MM;i++)
     16     {
     17         for(int j=1;j<=i;j++)
     18         {
     19             Sti[i][j]=(int)(Sti[i-1][j-1]+((LL)j*(LL)Sti[i-1][j])%mod)%mod;
     20         }
     21     }
     22 }
     23 void init()
     24 {
     25     stirling2();
     26     for(int i=0;i<5;i++)
     27     {
     28         bell[i][0]=1;
     29         for(int j=1;j<m[i];j++)
     30         {
     31             bell[i][j]=0;
     32             for(int k=1;k<=j;k++)
     33             {
     34                 bell[i][j]=(bell[i][j]+Sti[j][k])%m[i];
     35             }
     36 //            printf("%d	%d
    ",j,bell[i][j]);
     37         }
     38     }
     39 }
     40 struct Matrix
     41 {
     42     int mat[MM][MM];
     43 };
     44 
     45 Matrix multiply(Matrix a,Matrix b,int M)
     46 {
     47     Matrix c;
     48     memset(c.mat,0,sizeof(c.mat));
     49     for(int i=0;i<M;i++)
     50     {
     51         for(int j=0;j<M;j++)
     52         {
     53             if(a.mat[i][j]==0)continue;
     54             for(int k=0;k<M;k++)
     55             {
     56                 if(b.mat[j][k]==0)continue;
     57                 c.mat[i][k]=(c.mat[i][k]+a.mat[i][j]*b.mat[j][k])%M;
     58             }
     59         }
     60     }
     61     return c;
     62 }
     63 Matrix quickmod(Matrix a,int n,int M)
     64 {
     65     Matrix res;
     66 
     67     for(int i=0;i<M;i++)
     68     {
     69         for(int j=0;j<M;j++)
     70             res.mat[i][j]=(i==j);
     71     }
     72 
     73     while(n)
     74     {
     75         if(n&1) res=multiply(res,a,M);
     76         n>>=1;
     77         a=multiply(a,a,M);
     78     }
     79     return res;
     80 }
     81 
     82 int work(int n,int M,int k)
     83 {
     84     Matrix per;//基础矩阵;
     85     memset(per.mat,0,sizeof(per.mat));
     86     per.mat[0][M-1]=1;
     87 
     88     for(int i=1;i<M;i++)
     89     {
     90             per.mat[i][i]=per.mat[i][i-1]=1;
     91     }
     92 
     93     Matrix tmp=quickmod(per,n/(M-1),M);
     94 
     95     int ans[MM];
     96     for(int i=0;i<M;i++)
     97     {
     98         ans[i]=0;
     99         for(int j=0;j<M;j++)
    100         {
    101             ans[i]=(ans[i]+bell[k][j]*tmp.mat[i][j])%M;
    102         }
    103     }
    104     return ans[n%(M-1)];
    105 }
    106 void exgcd(int a,int b,int& d,int& x,int &y)
    107 {
    108     if(!b){d=a;x=1;y=0;}
    109     else
    110     {
    111         exgcd(b,a%b,d,y,x);
    112         y-=x*(a/b);
    113     }
    114 }
    115 int China(int r)
    116 {
    117     int Mc=1;
    118     int Mi,d,x,y,as=0;
    119     for(int i=0;i<r;i++)
    120     {
    121         Mc*=m[i];
    122     }
    123     for(int i=0;i<r;i++)
    124     {
    125         Mi=Mc/m[i];
    126         exgcd(Mi,m[i],d,x,y);
    127         as=(as+Mi*x*at[i])%Mc;
    128     }
    129     if(as<0) as+=Mc;
    130     return as;
    131 }
    132 int main()
    133 {
    134     int T,n;
    135     scanf("%d",&T);
    136 
    137     init();
    138     while(T--)
    139     {
    140         scanf("%d",&n);
    141         for(int i=0;i<5;i++)
    142         {
    143             at[i]=work(n,m[i],i);
    144         }
    145         int sol=China(5);
    146         printf("%d
    ",sol);
    147     }
    148 
    149     return 0;
    150 }

    时间过的好快,居然要期末考了,,,在学校的日子也不多了,aking2015......为了我们共同的梦!fighting!

  • 相关阅读:
    小程序苹果手机上video会盖住绝对定位的view层,小程序 video 层级,原生组件
    两个高斯分布乘积的理论推导
    两个高斯分布的和的分布——正态分布的再生性
    随机变量、随机向量和随机有限集的定义
    UdpClient.BeginReceive(AsyncCallback, Object) 方法
    基于C#的UDP协议的异步实现
    基于C#实现串口通信Demo
    pitch、yaw、roll三个角的区别
    dotNET Core 3.X 使用 Jwt 实现接口认证
    C#使用RabbitMQ
  • 原文地址:https://www.cnblogs.com/yuyixingkong/p/4489189.html
Copyright © 2020-2023  润新知