cf1559 E. Mocha and Stars
这个题我们可以看到有三个限制条件,如果将这三个式子综合一下,那么我们可以得到所求答案的式子。
\[ 令f(a_1,a_2,...a_n) 表示 \sum_{i=1}^{n} a_i \leq m是否成立
\]
所求即
\[ \sum_{a_1=l1}^{r1}\sum_{a_2=l2}^{r2}...\sum_{a_n=l_n}^{r_n} [\gcd(a_1,a_2...a_n)=1]*f(a_1,a_2,...a_n)
\]
这里根据莫比乌斯变换得
\[ =\sum_{a_1=l1}^{r1}\sum_{a_2=l2}^{r2}...\sum_{a_n=l_n}^{r_n} f(a_1,a_2,...a_n)\sum_{d|\gcd(a_1,a_2..a_n)} \mu(d)
\]
\[ =\sum_{d=1}^{m}\mu(d)\sum_{a_1=l1}^{r1}\sum_{a_2=l2}^{r2}...\sum_{a_n=l_n}^{r_n} \sum_{d|\gcd(a_1,a_2..a_n)} f(a_1,a_2,...a_n)
\]
\[ =\sum_{d=1}^{m}\mu(d)\sum_{a_1=\lceil \frac{l1}{d} \rceil}^{\lfloor \frac{r1}{d} \rfloor}\sum_{a_2=\lceil \frac{l2}{d} \rceil}^{\lfloor \frac{r2}{d} \rfloor}...\sum_{a_n=\lceil \frac{l_n}{d} \rceil}^{\lfloor \frac{r_n}{d} \rfloor} f(a_1,a_2,...a_n)
\]
对于后面
\[\sum_{a_1=\lceil \frac{l1}{d} \rceil}^{\lfloor \frac{r1}{d} \rfloor}\sum_{a_2=\lceil \frac{l2}{d} \rceil}^{\lfloor \frac{r2}{d} \rfloor}...\sum_{a_n=\lceil \frac{l_n}{d} \rceil}^{\lfloor \frac{r_n}{d} \rfloor} f(a_1,a_2,...a_n)
\]
我们用dp在\(O(\frac{n*m}{d})\)的时间内完成。
我们令\(dp[i][j]\)表示当前数和为\(j\)时并且到第\(i\)个数时的方法数,对于一个位置\(i\),$$dp[i][j] = \sum_{k=j-l_i}^{j-r_i}dp[i-1][k],运用滚动数组可以滚掉一维。$$
莫比乌斯函数可在线性时间得出,那么最后的时间复杂度即时\(\sum_{d=1}^m \frac{n*m}{d}=n*m*\log(m)\)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<map>
#include<vector>
#include<set>
#include<cmath>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define rpe(i,a,b) for(int i=a;i>=b;--i)
#define pts putchar('\n')
#define ptc putchar(' ')
#define pb push_back
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int>P;
const int inf=0x7f7f7f7f;
const ll linf=1e18;
const int maxn=1e5+9;
const int maxm=1e7+9;
const double PI=3.1415926;
const double eps=1e-5;
const ll mod=998244353;
const int base=131;
const int N=1e6;
namespace IO{
ll read(){
ll a=1,b=0;char c=getchar();
while(c>'9'||c<'0'){if(c=='-')a=-1;c=getchar();}
while(c>='0'&&c<='9'){b=(b<<3)+(b<<1)+c-'0';c=getchar();}
return a*b ;
}
void print (ll x){
if(x<0) putchar('-'),x=-x;
if(x>9) print(x/10);
putchar(x%10+'0');
}
}
using namespace IO;
int n,m;
int l[70],r[70];
int p[maxn],mu[maxn],cnt=0;
bool vis[maxn];
void pre(){n=1e5;
mu[1]=1;
rep(i,2,n){
if(!vis[i]) p[++cnt]=i,mu[i]=-1;
rep(j,1,cnt){
if(1LL*i*p[j]>n) break;
vis[i*p[j]]=1;
if(i%p[j]==0) break;
mu[i*p[j]]=-mu[i];
}
}
}
int s[maxn],f[maxn];
int solve(int d){
rep(i,1,m/d) f[i]=0;
f[0]=1;
rep(i,1,n){
int L = (l[i] + d -1)/d, R = r[i]/d;
if(L>R) return 0;
s[0]=f[0];
rep(j,1,m/d) s[j]=(s[j-1] + f[j])%mod;
rep(j,0,m/d){
f[j] = ( ((j-L>=0)? s[j-L]:0) - ((j>=R+1)? s[j-R-1]:0 )+mod)%mod;
}
}
ll sum=0;
rep(i,1,m/d) sum=(sum+f[i])%mod;
return sum;
}
int main(){
pre();
n=read(),m=read();
rep(i,1,n) l[i]=read(),r[i]=read();
ll ans=0;
rep(i,1,m) ans=(ans+ 1LL*mu[i]*solve(i)+mod)%mod;
print(ans%mod);
return 0;
}