hdoj 1299 Diophantus of Alexandria
链接:http://acm.hdu.edu.cn/showproblem.php?pid=1299
题意:求 1/x + 1/y = 1/n (x <= y) 的组数。
思路:转化为一个数的因子个数。
因为x,y,z 都是整数,令 y = n+k (倒数和相等,x,y 明显大于 n),带入式子可得 x = n*n / k + n ;所以 x 的组数就与k相关了,只要 k 满足是 n*n 的约数,组数就 +1。假设 n = (p1^r1) * (p2^r2) * (p3^r3) * ... * (pn^rn),则 n 的约数个数为 (r1+1) * (r2+1) * ... * (rn+1), n * n 可分解为 n * n = (p1^2r1) * (p2^2r2) * … *(pn^2rn), 所以 n*n 的约数个数为 cnt = (2r1+1) * (2r2+1) * … * (2rn+1)。公式中的 p1,p2,……,pn 为素数。所以就转化为求素数的问题,这里用到线性筛法求 sqrt(n)内的素数。因为 x < y, 所以把结果除以2就得到答案。
代码:
1 #include<iostream> 2 #include<cstring> 3 #include<cmath> 4 #include<cstdio> 5 using namespace std; 6 7 typedef long int LL; 8 const int maxv = 35000; 9 int prime[4000], num[maxv]; 10 11 void prim() //筛法求素数 12 { 13 int i, j, k = 1; 14 for(i = 2; i < maxv; ++i) num[i] = 1; 15 prime[0] = 2, num[4] = 0; 16 for(i = 3; i < maxv; i += 2) 17 { 18 if(num[i]) prime[k++] = i; 19 for(j = 0; (j<k && i*prime[j] < maxv); ++j) 20 { 21 num[i*prime[j]] = 0; 22 if(i%prime[j] == 0) break; 23 } 24 } 25 } 26 27 int counter(int n) //计算约数个数 28 { 29 int cnt = 1, i, j, k = 0; 30 int q; 31 i = (int)sqrt(n*1.0)+1; 32 for(j = 0; prime[j] <= i; ++j) 33 { 34 if(n % prime[j] == 0) 35 { 36 q = 0; 37 while(n%prime[j] == 0){ 38 n = n/prime[j], q++; 39 } 40 cnt *= (2*q+1); 41 } 42 } 43 44 if(n > 1) 45 cnt *= 3; 46 return (cnt+1)/2; 47 } 48 int main() 49 { 50 int n; 51 int i = 1, cnt, t; 52 prim(); 53 //freopen("hdoj1299.txt", "r", stdin); 54 cin >> t; 55 while(t--) 56 { 57 cin >> n; 58 cnt = counter(n); 59 cout<<"Scenario #" << i++ <<": " << cnt << endl << endl; 60 } 61 return 0; 62 }