现在的位置: 首页 > 综合 > 正文

poj 2992 Divisors 简单的数论问题

2013年10月14日 ⁄ 综合 ⁄ 共 1630字 ⁄ 字号 评论关闭

Divisors
Time Limit: 1000MS   Memory Limit: 65536K
Total 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 1
6 3
10 4

Sample Output

2
6
16

Source

算法分析:  数论中一个最简单的定理 要注意的是所有的树都可以分解成多个质数相乘的形式 例如 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);
    } 
    
    
}



抱歉!评论已关闭.