题目:
https://ac.nowcoder.com/acm/problem/20271
给定 n n n,在满足 ∑ i = 1 k a i = n , a i ≥ 1 \sum_{i=1}^{k}a_i=n,a_i\geq 1 ∑i=1kai=n,ai≥1的情况下。求有多少种 l c m ( a 1 , a 2 . . . a k ) lcm(a_1,a_2...a_k) lcm(a1,a2...ak)
思路:
假设
l
c
m
(
a
1
,
a
2
.
.
.
a
k
)
=
m
=
∏
i
=
1
x
p
i
b
i
lcm(a_1,a_2...a_k)=m=\prod_{i=1}^{x}p_i^{b_i}
lcm(a1,a2...ak)=m=∏i=1xpibi,因为
p
i
≤
n
p_i\le n
pi≤n,所以
x
<
n
x<n
x<n。可以构造令
a
1
=
p
1
b
1
,
a
2
=
p
2
b
2
.
.
.
a
x
=
p
x
b
x
a_1=p_1^{b_1},a_2=p_2^{b_2}...a_x=p_x^{b_x}
a1=p1b1,a2=p2b2...ax=pxbx,剩下的用
1
1
1补就能满足
∑
i
=
1
k
a
i
=
n
\sum_{i=1}^{k}a_i=n
∑i=1kai=n(最优的情况)。此时
∑
i
=
1
x
p
i
b
i
≤
n
\sum_{i=1}^{x}p_i^{b_i}\le n
∑i=1xpibi≤n
只要再证明
∑
i
=
1
x
p
i
b
i
>
n
\sum_{i=1}^{x}p_i^{b_i}>n
∑i=1xpibi>n无解。
证:
理想情况
a
1
=
p
1
b
1
k
1
,
a
2
=
p
2
b
2
k
2
.
.
.
a
x
=
p
x
b
x
k
x
(
g
c
d
(
p
i
,
k
i
)
=
1
)
a_1=p_1^{b_1}k_1,a_2=p_2^{b_2}k_2...a_x=p_x^{b_x}k_x(gcd(p_i,k_i)=1)
a1=p1b1k1,a2=p2b2k2...ax=pxbxkx(gcd(pi,ki)=1),此时
∑
i
=
1
x
a
i
>
n
\sum_{i=1}^{x}a_i>n
∑i=1xai>n
更坏的情况比如
a
1
=
p
1
b
1
k
1
,
a
2
=
p
2
b
2
k
2
.
.
.
a
x
−
1
=
p
x
−
1
b
x
−
1
p
x
b
x
k
x
−
1
a_1=p_1^{b_1}k_1,a_2=p_2^{b_2}k_2...a_{x-1}=p_{x-1}^{b_{x-1}}p_x^{b_x}k_{x-1}
a1=p1b1k1,a2=p2b2k2...ax−1=px−1bx−1pxbxkx−1
因为
a
1
≥
p
1
b
1
.
.
.
a
x
−
2
≥
p
x
−
2
b
x
−
2
,
a
x
−
1
≥
p
x
−
1
b
x
−
1
+
p
x
b
x
(
p
x
−
1
b
x
−
1
p
x
b
x
≥
p
x
−
1
b
x
−
1
+
p
x
b
x
)
a_1\ge p_1^{b_1}...a_{x-2}\ge p_{x-2}^{b_{x-2}},a_{x-1}\ge p_{x-1}^{b_{x-1}}+p_x^{b_x}\ (p_{x-1}^{b_{x-1}}p_x^{b_x}\ge p_{x-1}^{b_{x-1}}+p_x^{b_x})
a1≥p1b1...ax−2≥px−2bx−2,ax−1≥px−1bx−1+pxbx (px−1bx−1pxbx≥px−1bx−1+pxbx),所以
∑
i
=
1
x
−
1
a
i
>
n
\sum_{i=1}^{x-1}a_i>n
∑i=1x−1ai>n。所以无解。
综上只需要判断有多少种 b b b数组满足 ∑ i = 1 x p i b i ≤ n \sum_{i=1}^{x}p_i^{b_i}\le n ∑i=1xpibi≤n, p x p_x px为小于等于 n n n的最大质数。可以用背包 d p dp dp。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1000+5;
int pri[N],tot;
ll f[N];
bool vis[N];
int n;
void sieve(){
for(int i=2;i<=n;i++){
if(!vis[i]){
pri[++tot]=i;
}
for(int j=1;j<=tot;j++){
if(pri[j]*i>n) break;
vis[pri[j]*i]=1;
if(i%pri[j]==0) break;
}
}
}
int main()
{
scanf("%d",&n);
sieve();
f[0]=1;
for(int i=1;i<=tot;i++)
for(int j=n;j>=0;j--){
for(int k=pri[i];k<=j;k*=pri[i]){
f[j]+=f[j-k];
}
}
ll ans=0;
for(int i=0;i<=n;i++)ans+=f[i];
printf("%lld",ans);
return 0;
}