题意:求解小于n的数a,b求有多少对a,b满足lcm(a,b)==n;
分析:由算数基本定理(素数筛)n=〖p1〗^e1×〖p2〗^e2×?×〖pk〗^ek,若lcm(a,b)==n;
则:a=〖p1〗^a1×〖p2〗^a2×?×〖pk〗^ak;
b=〖p1〗^b1×〖p2〗^b2×?×〖pk〗^bk;
其中ai,bi都小于等于ei;
如果两个数的lcm(a,b)==n则有ai取最大值bi随意和bi取最大值ai随意,这样计算过后,每一种情况都计算了两次,只有(n,n)这种情况计算了一次。所以根据ai的值一共情况为(2*ei+1)种,因为都是两次,只有(n,n)是一次,所以最后的结果是。
代码如下:
#include <set> #include <map> #include <stack> #include <queue> #include <math.h> #include <vector> #include <utility> #include <string> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <algorithm> #include <functional> using namespace std; int k; long long suv[100500]; const int N=10000100; long long prime[N/10]={0}; int num_prime=0; bool isNotPrime[N]={1,1}; void su(){ for(long i = 2 ; i < N ; i ++){ if(!isNotPrime[i]) prime[num_prime++]=i; for(long j = 0 ; j < num_prime &&i*prime[j]<N ;j ++) { isNotPrime[i * prime[j]] = 1; if( !(i % prime[j]))break; } } } void prime_solve(long long n){ memset(suv,0,sizeof(suv)); for(long long i=0;i<num_prime&&prime[i]*prime[i]<=n;i++){ // cout<<prime[i]<<endl; if(n%prime[i]==0){ while(n%prime[i]==0){ n/=prime[i]; suv[k]++; } k++; } } if(n!=1)suv[k++]=1; }//用这种分解方法比较快 int main(){ int t; scanf("%d",&t); int m=1; su(); while(t--){ long long n; scanf("%lld",&n); k=0; prime_solve(n); long long sum=1; for(int i=0;i<k;i++) sum*=(2*suv[i]+1); printf("Case %d: %lld\n",m++,(sum+1)/2); } return 0; }
原文:http://blog.csdn.net/qq_27599517/article/details/50911218