zoukankan      html  css  js  c++  java
  • 【洛谷3653】小清新数学题(数论)

    点此看题面

    • (sum_{i=L}^Rmu(i))
    • (1le lle rle10^{18},r-lle10^5)

    一道有趣的数论题

    考虑(l,r)范围很大,我们最多只能筛出(10^6),也就是(O(sqrt[3]r))范围内的素数。

    对于一个需要求解的(mu(x)),我们可以先把它当中(le10^6)的质因子先全部除去,同时维护出这部分的(mu)值。

    而剩下的部分如果不为(1),则最多由两个(>10^6)的质因子相乘而得。

    如果剩下的是一个质数(可以用(MillerRabin)检测),那么答案就是在原(mu)值的基础上再乘个(-1)

    如果剩下的是一个平方数,那么答案就是(0)

    否则,剩下的是两个不同的大质数,那么答案就是在原(mu)值的基础上乘两次(-1),也就是原答案。

    前面除质因子的过程最好不要枚举数去找质因子,而是枚举质因子直接扫过区间中的数,这样就能避免无效枚举。

    代码:(O((r-l)log^2r))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 100000
    #define S 1000000
    #define LL long long
    using namespace std;
    int Mu[N+5];LL v[N+5];
    int Pt,P[S+5];I void Sieve() {for(RI i=2,j;i<=S;++i)
    	for(!P[i]&&(P[++Pt]=i),j=1;j<=Pt&&i*P[j]<=S;++j) if(P[i*P[j]]=1,!(i%P[j])) break;}
    namespace MR//MillerRabin素数测试
    {
    	const int pt=4,p[pt]={2,3,13,19};
    	I LL QM(Con LL& x,Con LL& y,Con LL& X) {return (x*y-(LL)(1.0L*x*y/X)*X+X)%X;}//快速乘
    	I LL QP(LL x,LL y,Con LL& X) {LL t=1;W(y) y&1&&(t=QM(t,x,X)),x=QM(x,x,X),y>>=1;return t;}//快速幂
    	I bool T(Con LL& x,CI p) {if(!(x%p)||QP(p,x-1,x)^1) return 0;//如果是倍数或不符合费马测试
    		LL k=x-1,t;W(!(k&1)) if((t=QP(p,k>>=1,x))^1) return t==x-1;return 1;}//二次探测直至不为1
    	I bool IsP(Con LL& x) {for(RI i=0;i^pt;++i) {if(x==p[i]) return 1;if(!T(x,p[i])) return 0;}return 1;}//枚举质数检测
    }
    int main()
    {
    	LL i,j,l,r;RI t=0;for(Sieve(),scanf("%lld%lld",&l,&r),i=l;i<=r;++i) v[i-l+1]=i,Mu[i-l+1]=1;//初始化每个数值为自身,μ为1
    	for(j=1;j<=Pt;++j) for(i=((l-1)/P[j]+1)*P[j]-l+1;i<=r-l+1;i+=P[j]) Mu[i]*=-1,!((v[i]/=P[j])%P[j])&&(Mu[i]=0);//枚举质因子去区间内更新
    	#define IsSqr(x) ((LL)sqrt(x)*(LL)sqrt(x)==(x))//判断平方数
    	for(i=1;i<=r-l+1;t+=Mu[i++]) Mu[i]&&v[i]^1&&(MR::IsP(v[i])?Mu[i]*=-1:IsSqr(v[i])&&(Mu[i]=0));//对剩余数判断是质数/平方数/两个大质数相乘
    	return printf("%d
    ",t),0;
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    【译】用 Chart.js 做漂亮的响应式表单
    【译】快速高效学习Java编程在线资源Top 20
    【译】理解Spring MVC Model Attribute 和 Session Attribute
    Github 恶搞教程(一起『玩坏』自己的 Github 吧)
    Effective Java 读书笔记(一):使用静态工厂方法代替构造器
    JavaScript 中 onload 事件绑定多个方法的优化建议
    【译】常见 Java 异常解释(恶搞版)
    Java 重写 equals 与 hashCode 的注意事项
    【译】Java语言速览:StackOverflow
    【译】StackOverflow——Java 中的 finally 代码块是否总会被执行?
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu3653.html
Copyright © 2011-2022 走看看