T1 最短路
T2 欧拉函数
给定常数 \(B\),\(T\) 组测试数据,每次给定 \(l,r\),求
\[\sum_{x=l}^r\varphi^{(\max_{i=1}^x\varphi(x)-B)}(x) \]当 \(\max_{i=1}^x\varphi(x)-B\leq 0\) 时 \(\varphi^{(\max_{i=1}^x\varphi(x)-B)}(x)=x\)
\(1\leq T\leq 10^5\),\(1\leq r,B\leq 10^9\)
暴力做 \(r\leq 10^6\) 拿到 \(72\) 分
其实很容易想到 \(\varphi\) 迭代 \(\log\) 次后就会变成 \(1\),但是一些具体的实现没有想到
对于 \(i\leq B\) 的贡献就是 \(i\),对于第一个 \(\varphi(x)>\log V+1\) 的 \(x\),\([x,r]\) 的贡献都是 \(1\)
问题是怎么找到这个 \(x\)
打表发现质数的密度并不小,而质数的 \(\varphi\) 值就是自己减 \(1\),所以 \(\max_{i=1}^x\varphi(x)\) 就约等于 \(i\) 前面的第一个质数的 \(\varphi\) 值。因此可以设一个阈值 \(M\),令 \(x=B+M+1\),这样对于 \([x,n]\) 的贡献都直接计算
对于 \([B,B+M]\) 的部分,暴力计算即可
#include<bits/stdc++.h>
#pragma GCC optimize(3,"Ofast","inline")
#define LL long long
using namespace std;
const int N=1e6+10,M=200;
int T,l,r,B;
LL g[M+10];
int getphi(int x)
{
int res=x;
for(int i=2; i*i<=x; i++)
{
if(x%i==0)
{
res=1LL*res*(i-1)/i;
while(x%i==0)
x/=i;
}
}
if(x>1)
res=1LL*res*(x-1)/x;
return res;
}
LL f(int k,int x)
{
if(k<=0)
return x;
if(k==1)
return (LL)getphi(x);
if(x==1)
return 1;
return f(k-1,getphi(x));
}
bool isprime(int x)
{
if(x==1)
return 0;
for(int i=2; i*i<=x; i++)
if(x%i==0)
return 0;
return 1;
}
void prework()
{
int mx=0;
for(int i=B+1; i<=B+M; i++)
{
if(isprime(i))
mx=i-1;
g[i-B]=f(mx-B,i)+g[i-B-1];
}
}
LL calc(int x)
{
if(x<=B)
return 1LL*(1+x)*x/2;
LL res1=1LL*(1+B)*B/2;
LL res2=g[min(x,B+M)-B];
if(x<=B+M)
return res1+res2;
LL res3=x-(B+M);
return res1+res2+res3;
}
void mian()
{
scanf("%d%d",&l,&r);
printf("%lld\n",calc(r)-calc(l-1));
}
int main()
{
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
scanf("%d%d",&T,&B);
prework();
while(T--)
mian();
return 0;
}
标签:10,int,res,2023.10,varphi,leq,测试,max
From: https://www.cnblogs.com/xishanmeigao/p/17742405.html