哈理工oj 1353-LCM与数对解题报告
链接:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1353
这道题是给一个数n要找出以n为最小公倍数的数对个数比如(3,4)的最小公倍数为12那(3,4)就算其中的一对,而对于(a,b)如果a!=b则(a,b)与(b,a)也算是不同的一对。这道题是一道数论题,要求能明白lcm(a,b)*gcd(a,b)=a*b的具体推导,假设a=p1^a1*p2^a2*p3*a3.........*pk^ak即为a的标准因子分解,假设其最小公倍数的标准分解也是这种形式,即c=p1^a1*p2^a2*p3*a3.........*pk^ak,则最大的a,b应该为c,如果a中p1的指数是在0-a1包括a1,之间那么a,b的最小公倍数一样是c所以,由此我们可以得出结论,其最小公倍数的数对的数量与其质因子标准分解式各个素数的指数有关,应为2*(a1+1)-1(考虑(a,b)和(b,a)两种情况以及(a,a)多算的情况所以乘2然后减一),则总共的数量应该为每一个的乘积
View Code
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define N 1000000 5 #define Nprime 78498//1000000以内的素数数量 6 using namespace std; 7 long long prime[Nprime]; 8 struct div 9 { 10 long long t; 11 long long i; 12 }; 13 int v[Nprime]; 14 bool mark[N]; 15 void init() 16 { 17 long long i,j,k; 18 j=0; 19 memset(mark,0,sizeof(mark)); 20 for(i=2;i<N;i++) 21 { 22 if(!mark[i]) 23 prime[j++]=i; 24 if(i<=1000) 25 for(k=2*i;k<N;k+=i) 26 mark[k]=true; 27 } 28 } 29 int main() 30 { 31 init();//素数筛选 32 long long i,j,k; 33 long long t; 34 scanf("%lld",&t); 35 long long n; 36 while(t--) 37 { 38 memset(v,0,sizeof(v)); 39 scanf("%lld",&n); 40 if(n==1) 41 { 42 printf("1\n"); 43 continue; 44 } 45 long long temp=n; 46 j=0; 47 bool p=true; 48 long long sum=1; 49 while(p) 50 { 51 for(i=0;prime[i]<=temp&&i<Nprime;i++) 52 { 53 if(temp%prime[i]==0) 54 { 55 v[i]++; 56 break; 57 } 58 } 59 if(temp==1||i>temp||i==Nprime) 60 p=false; 61 else 62 temp/=prime[i]; 63 } 64 if(temp==n) 65 { 66 printf("3\n"); 67 continue; 68 } 69 for(i=0;i<Nprime;i++) 70 if(v[i]>0) 71 { 72 sum*=(2*(v[i]+1)-1); 73 } 74 if(temp>999983)//此时temp是一个大于100万的素数 75 sum*=3; 76 printf("%lld\n",sum); 77 } 78 return 0; 79 }