LightOJ 1236 Pairs Forming LCM (LCM 唯一分解定理 + 素数筛选)
http://lightoj.com/volume_showproblem.php?problem=1236
我们可以利用唯一分离定理:
n = p1^x1*p2^x2*p3^x3*...*ps^xs;
n = lcm(i, j);
假设n = p1^x1;那么i、j有两种:
(1)i = p1^x1,则 j = p1^m(m属于[0,x1]), 这样(i,j)共有 (x1 + 1)种
(2)j = p1^x1,则 i = p1^n(n属于[0,x1]), 这样(i,j)共有 (x1 + 1)种
那么总共就有ans = 2*(x1 + 1)种,又因为当m = n时(1)和(2)这两种情况是一样的,所以最终总情况ans-1,即ans = 2*(x1 + 1) - 1 = 2*x1 + 1
当n = p1^x1*p2^x2*p3^x3*...*ps^xs时总情况ans = (2*x1+1)*(2*x2+1)*(2*x3+1)*...*(2*xs+1);
上面求的ans是i>j和i<j都可以即(i,j)和(j,i)重复了(除了(n,n)只算了一种),而题中求的是i<=j,所以ans /= 2;
还有一种(n,n)的情况得加上
#include<stdio.h> #include<math.h> #include<string.h> #include<stdlib.h> #include<algorithm> using namespace std; const int N = 1e7 + 10; typedef long long ll; int prime[700010], k; bool Isprime[N]; void Prime() { k = 0; memset(Isprime, true, sizeof(Isprime)); Isprime[1] = false; for(int i = 2 ; i < N ; i++) { if(Isprime[i]) { prime[k++] = i; for(int j = 2 ; i * j < N ;j++) Isprime[i * j] = false; } } }//素数筛选 int main() { int t, p = 0; ll n; Prime(); scanf("%d", &t); while(t--) { p++; int x; ll ans = 1; scanf("%lld", &n); for(int i = 0 ; i < k && prime[i] * prime[i] <= n; i++) { x = 0; if(n % prime[i] == 0) { while(n % prime[i] == 0) { x++; n /= prime[i]; } } ans *= (2 * x + 1); } if(n > 1) ans *= 3; printf("Case %d: %lld\n", p, ans / 2 + 1); } return 0; }