题目:
思路:
依题意如果将mod的顺序任意变化,答案不变,那么所有数必须要是最小的数的倍数。假设模数没有倍数关系,那么连续取模就会破坏数据。问题取决于最小元素
a
[
1
]
a[1]
a[1],之后就是在
a
[
1
]
a[1]
a[1]的倍数中取
k
−
1
k-1
k−1个,根据逆元组合数预处理出阶乘的逆元.
对阶乘的逆元有:
i
n
v
[
n
!
]
=
i
n
v
[
(
n
+
1
)
!
]
∗
(
n
+
1
)
%
m
o
d
inv[n!]=inv[(n+1)!]∗(n+1)\%mod
inv[n!]=inv[(n+1)!]∗(n+1)%mod
i n v [ n ! ] = 1 n ! = ( n ! ) m o d − 2 % m o d inv[n!]=\frac{1}{n!}=(n!)^{mod-2}\%mod inv[n!]=n!1=(n!)mod−2%mod
= 1 ( n + 1 ) ! ∗ ( n + 1 ) = ( ( n + 1 ) ! m o d − 2 % m o d ) ∗ ( n + 1 ) =\frac{1}{(n+1)!}*(n+1)=((n+1)!^{mod-2}\%mod)*(n+1) =(n+1)!1∗(n+1)=((n+1)!mod−2%mod)∗(n+1)
=
i
n
v
[
(
n
+
1
)
!
]
∗
(
n
+
1
)
%
m
o
d
=inv[(n+1)!]*(n+1)\%mod
=inv[(n+1)!]∗(n+1)%mod
测试一:
7 3
16
分析:
n=7,也就是从1,2,3,4,5,6,7中拿出k个成倍数关系的数字
当最小数a[1]=1的时候,从剩下的a[1]的倍数(n/1-1=6)中拿出(k-1=2)个数,有
C
6
2
=
15
C_{6}^{2}=15
C62=15
当最小数a[1]=2的时候,从剩下的a[1]的倍数(n/2-1=2)中拿出(k-1=2)个数,有
C
2
2
=
1
C_{2}^{2}=1
C22=1
当最小数a[1]=3的时候,从剩下的a[1]的倍数(n/3-1=1)中拿出(k-1=2)个数,有
C
1
2
=
0
C_{1}^{2}=0
C12=0
…
综上n=7,k=3的时候,有15+1=16种可能
我们可以推导出最终的结果为
∑
i
=
1
n
C
n
i
−
1
k
−
1
\sum_{i=1}^{n}C_{\frac{n}{i}-1}^{k-1}
∑i=1nCin−1k−1
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=998244353,maxn=5e5+5;
ll inv[maxn],fac[maxn],n,k,ans=0;
ll qpow(ll a,ll b) { //快速幂模板
ll res = 1,base = a;
while(b) {
if(b&1) res = res*base%mod;
base = base*base%mod;
b >>= 1;
}
return res;
}
void init() { //初始化 求阶乘和阶乘的逆元
fac[0]=1;
for(int i=1; i<maxn; i++) fac[i]=(fac[i-1]*i)%mod;
int t=5e5;
inv[t]=qpow(fac[t],1LL*(mod-2))%mod;
for(int i=t-1; i>=0; i--) inv[i]=inv[i+1]*(i+1)%mod;
}
ll C(ll x,ll y) { //组合数模板
if(x<y) return 0;
ll res=1;
y=min(x-y,y);
for(int i=x; i>=x-y+1; i--) res=res*i%mod;
res=res*inv[y]%mod;
return res;
}
int main() {
cin>>n>>k;
init();
for(int i=1; i<=n; i++) ans=(ans+C(n/i-1,k-1))%mod;
cout<<ans<<endl;
}