如果求解:
根据莫比乌斯的一般套路,很容易想到如下转化:
即将原式转化为莫比乌斯函数后交换求和顺序。
考虑问题二的限制,有:
,这部分就是个背包问题,假设
表示前
个数相加和为
的方案数。
那么转移方程有:
直接转移复杂度是的,注意到等式右边可以用前缀和维护,令
,则有:
显然只要先用更新
,再用
更新
就可以把第一维去掉,复杂度
。
很显然,我们只要枚举,然后跑一遍背包,总的复杂度就是
,近似等于
#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';
} 
京公网安备 11010502036488号