poj 2992 Divisors 简单的数论问题

来源:互联网 发布:php与mysql web开发五 编辑:程序博客网 时间:2024/05/02 01:22

Divisors
Time Limit: 1000MS Memory Limit: 65536KTotal Submissions: 8634 Accepted: 2453

Description

Your task in this problem is to determine the number of divisors of Cnk. Just for fun -- or do you need any special reason for such a useful computation?

Input

The input consists of several instances. Each instance consists of a single line containing two integers n and k (0 ≤ k ≤ n ≤ 431), separated by a single space.

Output

For each instance, output a line containing exactly one integer -- the number of distinct divisors of Cnk. For the input instances,this number does not exceed 263 - 1.

Sample Input

5 16 310 4

Sample Output

2616

Source

CTU Open 2005


算法分析:  数论中一个最简单的定理 要注意的是所有的树都可以分解成多个质数相乘的形式 例如 36可以分解成2*2*3*3 底数2的指数是2 底数3的指数是2,这样根据组合数学的原理 可以求出这个数所有的除数的个数   除数的个数=(各个位上指数+1)相乘  例如 324=2*2*3*3*3*3 就有两位,底数为2的指数为2 底数为3的指数为4 那么 324的除数有=(2+1)*(3+1)。

还要注意的是此题的数据量比较庞大,直接对每个数进行分解所占用的时间大,容易tle,要存储阶乘的质因数分解的结果能有效的提高运算的速度。

还要注意题目中 中标红的话  输出的结果会超过int的值

要注意的是 最好采用记忆化存储的方式 不用每次都对其进行分解,减少时间。

post code:


#include<stdio.h>#include<string.h>int used[432];int a[432][84];   //将阶乘按质因数分解的结果存储。int c[84];int d[84];int main(){    int i,j,len;    memset( used, 0, sizeof(used) );    for( i=2; i*i<432; i++ )        //筛选法求质数    {           if(used[i]==0)for(j=2*i; j<432; j+=i)                                 used[j]=1;          }      j=1;    for( i=2; i<432; i++ )   //将质数存放到c数组中        if(used[i]==0){                       c[j]=i;                       j++;                      }    len=j;    int m,n,num,flag=0;    memset( a, 0, sizeof(a) );     for( i=431; i>=2; i-- )    //对2-431进行质因数的分解           {               num=i;               for(j=1;j<84;j++)                 {                    while(num%c[j]==0)                    {                       a[i][j]++;                          num/=c[j];                                }                                        if(num==1)break;               }           }                   for( i=3; i<432; i++)         //将分解后的质因数进行阶乘的累积 由单个数的分解编程阶乘的分解           {                for( j=1; j<84; j++)                {                    a[i][j]+=a[i-1][j];                }           }      __int64 sum=1;    while( scanf("%d %d",&m,&n)!=EOF )    {                memset(d,0,sizeof(d));        for(i=1;i<len;i++)        {          d[i]=a[m][i]-a[m-n][i]-a[n][i]; //有点类似树状数组的求值 直接调用Cnk的分解形式                                               }                 sum=1;           for(i=1; i<len; i++)           {                 if(d[i]!=0){                              sum*=d[i]+1;     //求出最终结果                            }             }           printf("%I64d\n",sum);    }         }




原创粉丝点击