【唯一分解定理】LightOJ - 1236 Pairs Forming LCM
题意:
求1=<i<=n,1<=j<=n,lcm(i,j)=n的方案数。
思路:
n = p1 ^ e1 * p2 ^ e2 *…*pn ^ en
for i in range(1,n): ei 从0取到ei的所有组合
必能包含所有n的因子。
现在取n的两个因子a,b
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=2ei+1。除了(n,n)所有的情况都出现了两次那么满足a<=b的有(2ei+1))/2+1个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=2ei+1。
除了 (n, n) 所有的情况都出现了两次 那么满足a<=b的有 (2ei + 1)) / 2 + 1 个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=2ei+1。除了(n,n)所有的情况都出现了两次那么满足a<=b的有(2ei+1))/2+1个
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long LL;
const int N=1e7+5;
const int NN=1e6;
unsigned int prime[NN],cnt; //prime[N]会MLE
bool vis[N];
void is_prime()
{
cnt=0;
memset(vis,0,sizeof(vis));
for(int i=2;i<N;i++)
{
if(!vis[i])
{
prime[cnt++]=i;
for(int j=i+i;j<N;j+=i)
{
vis[j]=1;
}
}
}
}
int main()
{
is_prime();
int t;
cin>>t;
for(int kase=1;kase<=t;kase++)
{
LL n;
cin>>n;
int ans=1;
for(int i=0;i<cnt&&prime[i]*prime[i]<=n;i++)
{
if(n%prime[i]==0)
{
int e=0;
while(n%prime[i]==0)
{
n/=prime[i];
e++;
}
ans*=(2*e+1);
}
}
if(n>1)
ans*=(2*1+1);
printf("Case %d: %d\n",kase,(ans+1)/2);
}
}