/* * 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; }