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;
} 
posted @ 2021-08-22 18:13  Mr_cold  阅读(38)  评论(0编辑  收藏  举报