Pairs Forming LCM(唯一分解定理)

来源:互联网 发布:java 毫秒转日期 编辑:程序博客网 时间:2024/06/03 18:28

题目链接http://vjudge.net/contest/70017#problem/H

题目大意:在a,b中(a,b<=n)(1 ≤ n ≤ 10^14),有多少组(a,b) (a<b)满足lcm(a,b)==n;

素因子分解:n = p1 ^ e1 * p2 ^ e2 *..........*pn ^ en

若a,b为1~n中的任意两个数,则:

a=p1 ^ a1 * p2 ^ a2 *..........*pn ^ an

b=p1 ^ b1 * p2 ^ b2 *..........*pn ^ bn

gcd(a,b)=p1 ^ min(a1,b1) * p2 ^ min(a2,b2) *..........*pn ^ min(an,bn)

lcm(a,b)=p1 ^ max(a1,b1) * p2 ^ max(a2,b2) *..........*pn ^ max(an,bn)

题解:

先对n素因子分解,n = p1 ^ e1 * p2 ^ e2 *..........*pk ^ ek,

lcm(a,b)=p1 ^ max(a1,b1) * p2 ^ max(a2,b2) *..........*pk ^ max(ak,bk)

所以,当lcm(a,b)==n时,max(a1,b1)==e1,max(a2,b2)==e2,…max(ak,bk)==ek

当ai == ei时,bi可取 [0, ei] 中的所有数  有 ei+1 种情况,bi==ei时同理。

那么就有2(ei+1)种取法,但是当ai = bi = ei 时有重复,所以取法数为2(ei+1)-1=2*ei+1。
除了 (n, n) 所有的情况都出现了两次  那么满足a<=b的有 (2*ei + 1)) / 2 + 1 

AC代码:

#include<stdio.h>#include<algorithm>#include<iostream>#include<string.h>using namespace std;typedef long long LL;const int mann=1e7+5;bool p[mann];LL prime[mann/10],k;void init()//素数筛法打表{    k=0;    memset(p,0,sizeof(p));    p[0]=p[1]=1;    for(LL i=2; i<mann; i++)    {        if(!p[i])        {            prime[k++]=i;            for(LL j=i+i; j<mann; j+=i)                p[j]=1;        }    }}int main(){    int t,T=0;    cin>>t;    init();    while(t--)    {        LL n,sum=1;//        for(int i=0;i<20;i++)//            printf("%d ",prime[i]);        cin>>n;        for(LL i=0; i<k&&prime[i]*prime[i]<=n; i++)        {            LL ans=0;            while(n%prime[i]==0)            {//求prime[i]在n中出现的次数                n/=prime[i];                ans++;            }            sum*=(2*ans+1);        }        if(n>1)            sum*=(2*1+1);        printf("Case %d: %lld\n",++T,(sum+1)/2);    }    return 0;}



0 0