题目链接
题目解法
我们发现这道题给出的性质比较特殊,所以考虑一些性质
考虑对于两个正整数
a
,
b
(
a
<
b
)
a,b(a<b)
a,b(a<b),满足
(
x
%
a
)
%
b
=
(
x
%
b
)
%
a
(x \%a)\%b=(x\%b)\%a
(x%a)%b=(x%b)%a
因为
a
<
b
a<b
a<b,所以
x
%
a
=
(
x
%
b
)
%
a
x\%a=(x\%b)\%a
x%a=(x%b)%a
所以
x
≡
x
%
b
(
m
o
d
a
)
x\equiv x\%b(mod\;a)
x≡x%b(moda)
若
x
=
q
b
+
r
x=qb+r
x=qb+r,那么
q
b
+
r
≡
r
(
m
o
d
a
)
qb+r\equiv r(mod\;a)
qb+r≡r(moda)
要使上式对于任意的
q
q
q 都成立,当且仅当
a
∣
b
a|b
a∣b
推广到
k
k
k 个数时,可以发现要使每个排列的结果都为
x
%
a
1
x\%a_1
x%a1,即排列顺序为
(
x
%
a
1
)
%
.
.
.
%
a
n
(x\%a_1)\%...\%a_n
(x%a1)%...%an
所以其他排列时,
a
1
a_1
a1 后面的数无需考虑,前面的数都必须是
a
1
a_1
a1 的倍数
所以可以得到,一个数列合法,当且仅当所有数都是
a
1
a_1
a1 的倍数
所以枚举
a
1
a_1
a1,在
a
1
a_1
a1 的倍数中取
k
−
1
k-1
k−1 个数即可
加上预处理,时间复杂度
O
(
n
l
o
g
n
)
O(n logn)
O(nlogn),可以
O
(
n
)
O(n)
O(n)
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N(500100),P(998244353);
int n,k,fac[N],inv[N];
inline int read(){
int FF=0,RR=1;
char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
return FF*RR;
}
int C(int a,int b){
if(a<b) return 0;
return (LL)fac[a]*inv[b]%P*inv[a-b]%P;
}
int qmi(int a,int b){
int res=1;
for(;b;b>>=1){
if(b&1) res=(LL)res*a%P;
a=(LL)a*a%P;
}
return res;
}
int main(){
fac[0]=inv[0]=1;
for(int i=1;i<N;i++){
fac[i]=(LL)fac[i-1]*i%P;
inv[i]=(LL)inv[i-1]*qmi(i,P-2)%P;
}
n=read(),k=read();
int ans=0;
for(int i=1;i<=n;i++) (ans+=C(n/i-1,k-1))%=P;
printf("%d",ans);
return 0;
}