Codeforces --Modular Stability(逆元+组合数+快速幂)

题目:

在这里插入图片描述
在这里插入图片描述

思路:

  依题意如果将mod的顺序任意变化,答案不变,那么所有数必须要是最小的数的倍数。假设模数没有倍数关系,那么连续取模就会破坏数据。问题取决于最小元素 a [ 1 ] a[1] a[1],之后就是在 a [ 1 ] a[1] a[1]的倍数中取 k − 1 k-1 k1个,根据逆元组合数预处理出阶乘的逆元.
对阶乘的逆元有: 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!)mod2%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)!mod2%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=1nCin1k1

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;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值