数论(分解质因数 + 组合计数) - Pairs Forming LCM - LightOJ 1236
题意:
计
算
满
足
i
和
j
的
最
小
公
倍
数
为
n
的
不
同
数
对
(
i
,
j
)
的
个
数
,
i
≤
j
。
优
化
上
述
函
数
。
计算满足i和j的最小公倍数为n的不同数对(i,j)的个数,i ≤ j。优化上述函数。
计 算 满 足 i 和 j 的 最 小 公 倍 数 为 n 的 不 同 数 对 ( i , j ) 的 个 数 , i ≤ j 。 优 化 上 述 函 数 。
Input
Input starts with an integer T (≤ 200), denoting the number of test cases.
Each case starts with a line containing an integer n (1 ≤ n ≤ 1014 ).
Output
For each case, print the case number and the value returned by the function ‘pairsFormLCM(n)’.
Sample Input
15
2
3
4
6
8
10
12
15
18
20
21
24
25
27
29
Sample Output
Case 1: 2
Case 2: 2
Case 3: 3
Case 4: 5
Case 5: 4
Case 6: 5
Case 7: 8
Case 8: 5
Case 9: 8
Case 10: 8
Case 11: 5
Case 12: 11
Case 13: 3
Case 14: 4
Case 15: 2
T
i
m
e
l
i
m
i
t
:
2000
m
s
,
M
e
m
o
r
y
l
i
m
i
t
:
32768
k
B
Time\ limit:2000 ms,Memory \ limit:32768 kB
T i m e l i m i t : 2 0 0 0 m s , M e m o r y l i m i t : 3 2 7 6 8 k B
分析:
扫描二维码关注公众号,回复:
11517221 查看本文章
假
设
n
是
a
和
b
的
最
小
公
倍
数
,
设
:
假设n是a和b的最小公倍数,设:
假 设 n 是 a 和 b 的 最 小 公 倍 数 , 设 :
a
=
p
1
a
1
×
p
2
a
2
×
.
.
.
×
p
n
a
n
a=p_1^{a_1}×p_2^{a_2}×...×p_n^{a_n}
a = p 1 a 1 × p 2 a 2 × . . . × p n a n
b
=
p
1
b
1
×
p
2
b
2
×
.
.
.
×
p
n
b
n
b=p_1^{b_1}×p_2^{b_2}×...×p_n^{b_n}
b = p 1 b 1 × p 2 b 2 × . . . × p n b n
a
i
,
b
i
≥
0
,
1
≤
i
≤
n
。
a_i,b_i≥0,1≤i≤n。
a i , b i ≥ 0 , 1 ≤ i ≤ n 。
则
:
则:
则 :
g
c
d
(
a
,
b
)
=
p
1
m
i
n
(
a
1
,
b
1
)
×
p
2
m
i
n
(
a
2
,
b
2
)
×
.
.
.
×
p
n
m
i
n
(
a
n
,
b
n
)
gcd(a,b)=p_1^{min(a_1,b_1)}×p_2^{min(a_2,b_2)}×...×p_n^{min(a_n,b_n)}
g c d ( a , b ) = p 1 m i n ( a 1 , b 1 ) × p 2 m i n ( a 2 , b 2 ) × . . . × p n m i n ( a n , b n )
l
c
m
(
a
,
b
)
=
p
1
m
a
x
(
a
1
,
b
1
)
×
p
2
m
a
x
(
a
2
,
b
2
)
×
.
.
.
×
p
n
m
a
x
(
a
n
,
b
n
)
lcm(a,b)=p_1^{max(a_1,b_1)}×p_2^{max(a_2,b_2)}×...×p_n^{max(a_n,b_n)}
l c m ( a , b ) = p 1 m a x ( a 1 , b 1 ) × p 2 m a x ( a 2 , b 2 ) × . . . × p n m a x ( a n , b n )
记
m
a
x
(
a
i
,
b
i
)
=
e
i
,
记max(a_i,b_i)=e_i,
记 m a x ( a i , b i ) = e i ,
则
n
=
p
1
e
1
×
p
2
e
2
×
.
.
.
×
p
n
e
n
则n=p_1^{e_1}×p_2^{e_2}×...×p_n^{e_n}
则 n = p 1 e 1 × p 2 e 2 × . . . × p n e n
要
求
不
同
数
对
(
a
,
b
)
的
数
量
,
对
于
每
一
个
素
因
子
p
i
,
要求不同数对(a,b)的数量,对于每一个素因子p_i,
要 求 不 同 数 对 ( a , b ) 的 数 量 , 对 于 每 一 个 素 因 子 p i ,
在
a
中
取
p
i
e
i
,
在
b
中
可
取
p
0
,
p
1
,
.
.
.
,
p
e
i
,
共
e
i
+
1
种
不
同
取
值
,
在a中取p_i^{e_i},在b中可取p^{0},p^1,...,p^{e_i},共e_i+1种不同取值,
在 a 中 取 p i e i , 在 b 中 可 取 p 0 , p 1 , . . . , p e i , 共 e i + 1 种 不 同 取 值 ,
反
过
同
理
,
故
方
案
数
为
C
2
1
×
(
e
i
+
1
)
−
1
,
−
1
是
为
了
去
掉
重
复
统
计
的
a
i
=
b
i
=
e
i
的
情
况
。
反过同理,故方案数为C_2^1×(e_i+1)-1,-1是为了去掉重复统计的a_i=b_i=e_i的情况。
反 过 同 理 , 故 方 案 数 为 C 2 1 × ( e i + 1 ) − 1 , − 1 是 为 了 去 掉 重 复 统 计 的 a i = b i = e i 的 情 况 。
那
么
总
的
方
案
数
为
:
s
u
m
=
∏
i
=
1
n
2
×
(
e
i
+
1
)
−
1
那么总的方案数为:sum=\prod_{i=1}^n2×(e_i+1)-1
那 么 总 的 方 案 数 为 : s u m = ∏ i = 1 n 2 × ( e i + 1 ) − 1
另
外
,
本
题
要
求
a
≤
b
,
因
此
总
方
案
数
还
需
除
2
。
另外,本题要求a≤b,因此总方案数还需除2。
另 外 , 本 题 要 求 a ≤ b , 因 此 总 方 案 数 还 需 除 2 。
需
注
意
a
i
=
b
i
=
e
i
的
情
况
我
们
只
统
计
了
一
次
,
除
2
后
由
于
下
取
整
的
缘
故
,
还
要
再
累
加
上
1
。
需注意a_i=b_i=e_i的情况我们只统计了一次,除2后由于下取整的缘故,还要再累加上1。
需 注 意 a i = b i = e i 的 情 况 我 们 只 统 计 了 一 次 , 除 2 后 由 于 下 取 整 的 缘 故 , 还 要 再 累 加 上 1 。
具体细节:
①
、
筛
出
n
内
的
质
数
,
然
后
对
输
入
的
n
进
行
质
因
数
分
解
。
①、筛出\sqrt{n}内的质数,然后对输入的n进行质因数分解。
① 、 筛 出 n
内 的 质 数 , 然 后 对 输 入 的 n 进 行 质 因 数 分 解 。
注
意
空
间
不
能
超
,
1
0
7
内
的
质
数
不
超
过
7
×
1
0
5
,
数
组
开
7
×
1
0
5
足
够
。
\qquad注意空间不能超,10^7内的质数不超过7×10^5,数组开7×10^5足够。
注 意 空 间 不 能 超 , 1 0 7 内 的 质 数 不 超 过 7 × 1 0 5 , 数 组 开 7 × 1 0 5 足 够 。
②
、
对
输
入
的
每
个
n
进
行
质
因
数
分
解
,
计
算
每
个
质
因
数
的
质
数
,
根
据
乘
法
原
理
进
行
计
数
。
②、对输入的每个n进行质因数分解,计算每个质因数的质数,根据乘法原理进行计数。
② 、 对 输 入 的 每 个 n 进 行 质 因 数 分 解 , 计 算 每 个 质 因 数 的 质 数 , 根 据 乘 法 原 理 进 行 计 数 。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define ll long long
using namespace std;
const int N= 1e7 + 10 ;
int primes[ 700000 ] , cnt;
bool st[ N] ;
void get_prime ( int n)
{
for ( int i= 2 ; i<= n; i++ )
{
if ( ! st[ i] ) primes[ cnt++ ] = i;
for ( int j= 0 ; primes[ j] * i<= n; j++ )
{
st[ primes[ j] * i] = true ;
if ( i% primes[ j] == 0 ) break ;
}
}
}
ll solve ( ll x)
{
ll sum= 1 ;
int sq= sqrt ( x) ;
for ( int i= 0 ; i< cnt && primes[ i] <= sq; i++ )
{
int p= primes[ i] ;
if ( x% p== 0 )
{
int cnt= 0 ;
while ( x% p== 0 )
{
x/ = p;
cnt++ ;
}
sum* = 2 * ( cnt+ 1 ) - 1 ;
}
}
if ( x> 1 ) sum* = 2 * ( 1 + 1 ) - 1 ;
return sum/ 2 + 1 ;
}
int main ( )
{
get_prime ( N- 1 ) ;
int T; cin>> T;
for ( int t= 1 ; t<= T; t++ )
{
ll n; cin>> n;
printf ( "Case %d: %lld\n" , t, solve ( n) ) ;
}
return 0 ;
}