lightoj 1341 Aladdin and the Flying Carpet
链接:http://lightoj.com/volume_showproblem.php?problem=1341
题意:给定整数 a, b ,求 区间[b, a] 内的 a 的约数对的个数,a 的约数对(比如[2, 3] 与 [3, 2] 是同一对),也就是说前因子要小于后因子。
思路:我的思路比较直接,就是求 a 的约数的个数(用欧拉函数),除以 2 就得到约数对数, 然后暴力求解区间 [1, b] 内的 a 的约数。最后两数相减得到结果。
代码:
1 #include <iostream> 2 #include <stdio.h> 3 #include <algorithm> 4 #include <queue> 5 #include <map> 6 #include <set> 7 #include <vector> 8 #include <cstring> 9 #include <math.h> 10 using namespace std; 11 12 typedef long long LL; 13 const int maxv = 1000005; 14 bool nu[maxv]; 15 int phi[80000], k; 16 17 void prime() //素数表 18 { 19 memset(nu, 0, sizeof(nu)); 20 int i, j; 21 k = 1; 22 nu[4] = 1, phi[0] = 2; 23 for(i = 3; i < maxv; i += 2) 24 { 25 if(!nu[i]) phi[k++] = i; 26 for(j = 0; j < k && i * phi[j] < maxv; j++) 27 { 28 nu[i*phi[j]] = 1; 29 if(!(i % phi[j])) break; 30 } 31 } 32 } 33 34 LL gain_ans(LL a) //得到区间[1, a] 的约数对数 35 { 36 int i = 0, j; 37 LL s = 1; 38 if(a == 0) return 0; 39 while(phi[i] < a && i < k ) //欧拉函数 40 { 41 j = 0; 42 if(a % phi[i] == 0) 43 while(a % phi[i] == 0) 44 a /= phi[i], j++; 45 s *= (j+1); 46 i++; 47 } 48 if(a != 1) s *= 2; 49 return s / 2; 50 } 51 52 int main() 53 { 54 LL b, a, s, q; 55 int t, cs = 1; 56 prime(); 57 freopen("lightoj1341.txt", "r", stdin); 58 cin >> t; 59 while(t--) 60 { 61 scanf("%lld%lld", &a, &b); 62 q = 0; 63 if(b >= sqrt(a)) s = 0; // b 大小限定 64 else 65 { 66 q = 0; 67 for(int i = 1; i < b; ++i) //暴力枚举 [1, b] 的a 的约数 68 if(a % i == 0) q++; 69 s = gain_ans(a) - q; 70 } 71 printf("Case %d: %lld\n", cs++, s); 72 } 73 return 0; 74 }