洛谷P5438 【XR-2】记忆

考虑 \(L=1\)
首先我们令一个数可以表示为 \(k^2a\) 的形式,其中 \(a\) 中没有平方因子
我们可以枚举 \(a\) ,假设在询问区间内的可以表示为 \(k^2a\) 形式的数字有 \(x\)
那么其对答案的贡献就为 \(x-1\)
转换题意,其实就是询问区间内 \(k^2a\)\(k=1\) 的数的个数
这里用到了新的东西

莫比乌斯容斥

其实就是用总个数
减去(平方因子中质数种类至少为1的数)
加上(平方因子中质数种类至少为2的数)
减去(平方因子中质数种类至少为3的数)
加上(平方因子中质数种类至少为4的数)...

总的来说 :

\[Cals(n)=\sum_{i=1}^{\sqrt {n}} \mu(i)\left \lfloor \frac{n}{i^2} \right \rfloor \]

考虑 \(L!=1\) 的情况
开始时我们的初始答案为 \((R-L+1)-Cals(R)-Cals(L-1)\)
考虑某个数 \(x=k^2a\)
如果 \(a<L\) ,那我们实际上是要减去 \(1\)的,但是我们并没有减去
那么接下来就是要找符合上述条件的 \(a\)
我们可以枚举 \(k\) ,那 \(a\) 的范围就是 \((\frac{L-1}{k^2},\frac{R}{k^2}]\)
然后让答案减去 \(Cals(\frac{R}{k^2})-Cals(\frac{L-1}{k^2})\) 就好了

Code
#include <bits/stdc++.h>
#define re register
#define int long long
// #define lls long long
#define pir make_pair
#define fr first 
#define sc second
#define db double
using namespace std;
const int mol=1e9+7;
const int maxn=1e7+10;
const int INF=1e18+10;
inline int qpow(int a,int b) { int ans=1; while(b) { if(b&1) (ans*=a)%=mol; (a*=a)%=mol; b>>=1; } return ans; }
inline int read() {
    int s=0,w=1; char ch=getchar();
    while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') { s=s*10+ch-'0'; ch=getchar(); }
    return s*w;
}

int L,R,lims,tot,prim[maxn],mu[maxn],sum[maxn],ansl[maxn]; bool vis[maxn];
inline void sleve() {
    mu[1]=1; lims=maxn-1;
    for(re int i=2;i<=lims;i++) {
        if(!vis[i]) { prim[++tot]=i; mu[i]=-1; }
        for(re int j=1;j<=tot&&prim[j]*i<=lims;j++) {
            vis[i*prim[j]]=1; if(i%prim[j]==0) break;
            mu[i*prim[j]]=-mu[i]; 
        }
    }
    for(re int i=1;i<=lims;i++) sum[i]=sum[i-1]+mu[i],ansl[i]=ansl[i-1]+(mu[i]!=0);
}
inline int cals(int n) {
    if(n<=lims) return ansl[n]; 
    int ans=0;
    for(re int l=1,r;l*l<=n;l=r+1) { r=sqrt(n/(n/(l*l))); ans+=(sum[r]-sum[l-1])*(n/(l*l)); } 
    return ans;
}
signed main(void) {
    // freopen("erp.in","r",stdin);
    sleve(); L=read(); R=read(); 
    int ans=R-L+1-cals(R)+cals(L-1);
    for(re int i=1,l,r,las=L-1;i*i<=R;i++) {
        l=(L-1)/(i*i); r=min(R/(i*i),las);
        ans-=cals(r)-cals(l); las=l;
    }
    printf("%lld\n",ans);
}
posted @ 2021-10-31 16:05  zJx-Lm  阅读(33)  评论(0编辑  收藏  举报