题意:
给定n和k
要求构造出一个长度为k的数组a
满足:
数组a中的数都在[1,n]以内,且两两不同,同时a(1)<a(2)<a(3)<…<a(n)
对于任意整数x,无论怎样打乱数组a的元素顺序,x%a(1)%a(2)%a(3)…%a(n)的值都不变
只需要统计能构造出多少组这样的数组即可
答案为998244353取模
数据范围:n,k<=5e5
解法:
对于x%a%b和x%b%a,只有当a=kb或者b=ka的情况下才不变(即倍数关系)
也可以说是gcd(a,b)=min(a,b)的情况下才不变
因为a(1)最小,那么只要确定了a(1),其他数都必须是a(1)的倍数
[1,n]中a(1)的倍数有n/a(1)个,去掉a(1)就是n/a(1)-1个,从中选出k-1个的方案数为组合数C(n/a(i)-1,k-1)
枚举a(1)累加答案即可
code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod=998244353;
const int N=5e5+5;
int fac[N];
int inv[N];
int ppow(int a,int b,int mod){
int ans=1%mod;a%=mod;
while(b){
if(b&1)ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
int C(int n,int m){
if(m<0||m>n)return 0;
return fac[n]*inv[m]%mod*inv[n-m]%mod;
}
signed main(){
fac[0]=1;
for(int i=1;i<N;i++){
fac[i]=fac[i-1]*i%mod;
}
inv[N-1]=ppow(fac[N-1],mod-2,mod);
for(int i=N-2;i>=0;i--){
inv[i]=inv[i+1]*(i+1)%mod;
}
//
int n,k;cin>>n>>k;
int ans=0;
for(int i=1;i<=n;i++){
int cnt=n/i-1;
ans=(ans+C(cnt,k-1))%mod;
}
cout<<ans<<endl;
return 0;
}