如果求解:
根据莫比乌斯的一般套路,很容易想到如下转化:
即将原式转化为莫比乌斯函数后交换求和顺序。
考虑问题二的限制,有:
,这部分就是个背包问题,假设表示前个数相加和为的方案数。
那么转移方程有:
直接转移复杂度是的,注意到等式右边可以用前缀和维护,令,则有:
显然只要先用更新,再用更新就可以把第一维去掉,复杂度。
很显然,我们只要枚举,然后跑一遍背包,总的复杂度就是,近似等于
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1e5+7,mod=998244353; int mu[maxn],L[55],R[55],l[55],r[55]; ll sum[maxn],f[maxn]; int main() { int n,m,tot; cin>>n>>m; for(int i=1;i<=n;++i) cin>>L[i]>>R[i]; mu[1]=1; for(int i=1;i<=m;++i) for(int j=i+i;j<=m;j+=i) mu[j]-=mu[i]; ll ans(0); for(int d=1;d<=m;++d) { if(!mu[d]) continue; for(int i=1;i<=n;++i) l[i]=(L[i]+d-1)/d,r[i]=R[i]/d; tot=m/d; for(int i=0;i<=tot;++i) sum[i]=1; for(int i=1;i<=n;++i) { for(int j=1;j<=tot;++j) f[j]=0; for(int j=l[i];j<=tot;++j) { f[j]=sum[j-l[i]]; if(j-r[i]-1>=0) f[j]=(f[j]-sum[j-r[i]-1]+mod)%mod; } sum[0]=0; for(int j=1;j<=tot;++j) sum[j]=(sum[j-1]+f[j])%mod; } ans=(ans+mu[d]*sum[tot])%mod; } cout<<(ans+mod)%mod<<'\n'; }