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;
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    .net core读取appsettings.config中文乱码问题
    vs2017错误:当前页面的脚本发生错误
    VS Code中无法识别npm命令
    Visual Studio报错/plugin.vs.js,行:1074,错误:缺少标识符、字符串或数字
    记录一次在生成数据库服务器上出现The timeout period elapsed prior to completion of the operation or the server is not responding.和Exception has been thrown by the target of an invocation的解决办法
    Java集合框架
    java hash表
    Java Dictionary 类存储键值
    java数据结构 栈stack
    java封装
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu3653.html
Copyright © 2011-2022 走看看