Uva 10139 Factovisors

/*
*   url: http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1080
*   stratege: 将除数m进行分解,分别求出质因子及其个数,然后对n进行判断,n中是否包含m的每个质因子下的个数,如果有,则可整除
*   Test Case: 16 32768 yes, 32768 = 2^15, 16!包含15个因子2,可整除
*   Status: 10537360	10139	Factovisors	Accepted	C++	2.820	2012-08-29 07:45:15
*   Author: johnsondu
*/

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std ;

#define LL long long
const int MAXN = 50000 ;
bool isPrime[MAXN] ;
int p[MAXN], prilen ;
bool flag ;
LL n, m ;
LL f[35][2], flen ;

void getPrime ()  //筛选素数
{
    int i ;
    memset (isPrime, true, sizeof (isPrime)) ;
    isPrime[0] = isPrime[1] = false ;
    for (i = 4; i < MAXN; i += 2)
        isPrime[i] = false ;
    p[0] = 2, prilen = 1 ;
    for (i = 3; i < MAXN; i += 2)
    {
        if (isPrime[i])
        {
            p[prilen ++] = i ;
            for (int j = 2*i; j < MAXN; j += i)
                isPrime[j] = false ;
        }
    }
}

void divide ()
{
    flen = 0 ;
    LL i, tp = m ;
    memset (f, 0, sizeof (f)) ;
    for (i = 0; (LL)p[i]*p[i] <= tp; i ++)
    {
        if (tp % p[i] == 0)
        {
            f[flen][0] = p[i] ;       //保存质因子
            while (tp % p[i] == 0)
            {
                f[flen][1] ++ ;       //该质因子下的数量
                tp /= p[i] ; 
            }
            flen ++ ;
        }
    }
    if (tp == m && n < m)
    {
        flag = true ;
    }

    if(tp > 1)
    {
        f[flen][0] = tp ;
        f[flen][1] = 1 ;
        flen ++ ;
    }
        
}

void solve ()
{
    flag = false ;
    divide () ;
    
    for (int i = 0; i < flen; i ++)  //假设测试案例为16, 32728, 16的阶乘中有15个为2的质因子,
    {
        int t = (int)((log(n*1.0))/(log(f[i][0]*1.0))) ; //(1)假设m的第一个质因子为x, 则此处是求x^1, x^2, x^3,.. 一共有有p项 
        int tmp = t ;
        int tt = 0 ;
        for (int j = 1; j <= tmp-3; j ++) //比如当前质因子为2,则3*2*2 = 12也在16内,此时多一个2, 通过验算
            tt += j*j ;                   //出现这类类似情况时,是从x^3以后开始出现,并且多出的个数为1, 4, 9,..为平方数。这里求多出的质因子的个数
        t = t*(t+1)/2 ;  //在(1)下,m的质因子的总和的个数,比如m为16,在(1)中求出t = 4, 则有2^1, 2^2, 2^3, 2^4, 共有10个2
        t = (n/f[i][0]-tmp) + t + tt ;  //(n/f[i][0]-tmp) 表示普通的能被2直接整除的个数,比如6 = 2*3, 12=2*6..
        if (t < f[i][1])  //如果个数小于m中质因子的个数,显然无法整除
        {
            flag = true ;
            break ;
        }
        if (flag)
            break ;
    }
    if (flag)
        printf ("%lld does not divide %lld!\n", m, n) ;
    else printf ("%lld divides %lld!\n", m, n) ;
}

int main ()
{
    getPrime () ;
    while (scanf ("%lld%lld", &n, &m) != EOF)
    {
        if (m < MAXN)
        {
            if (isPrime[m] && n < m)
            {
                printf ("%lld does not divide %lld!\n", m, n) ;
                continue ;
            }
        }
        if (m == 0)
        {
            printf ("%lld does not divide %lld!\n", m, n) ;
            continue ;
        }
        if (m == 1)
        {
            printf ("%lld divides %lld!\n", m, n) ;
            continue ;
        }
        solve () ;
    }
    return 0; 
}

你可能感兴趣的:(测试,url,360)