B.日记和欧拉函数

题意

给定 \(L,R,B\),求 \(\sum_{i=L}\limits^{R}\varphi^{\left(\max_{j=1}^i\varphi(j)-B\right)}(i)\).


思路

注:此文中 \(p\) 均代表质数。

首先,观察到 \(\varphi^k(x)\) 是一个下降很快的函数,\(k\) 不用很大就可以达到不动点 \(1\)。证明如下:

分类讨论。
\(x\equiv 0\pmod 2\),则只有奇数与 \(x\) 互质,于是 \(\varphi(x)\le\frac x2\)
\(x\equiv 1\pmod 2\),若 \(i\)\(x\) 互质,则 \(x-i\) 必定也与 \(x\) 互质。则 \(\varphi(x)\) 为偶数。
所以至多 \(2\) 次即可将 \(x\) 降到 \(\frac x2\) 以下,即 \(k\) 的上界为 \(2\left\lceil\log_2(x)\right\rceil\)

其次,我们观察 \(\max_{j=1}^i\varphi(j)-B\),不妨令 \(m(x)=\max_{j=1}^x\varphi(j)\)

1.当 \(x\le B\) 时,\(m(x)\le x \le B\)。则此时 \(f(x)=x\)
2.当 \(x\ge p\ge B+l\)\(l\) 为常数,约为 \(400\))时,\(m(x)\ge\varphi(p)=p-1\ge B+l-1\)。则此时 \(k\) 太大,可以直接将 \(f(x)\) 看成 \(1\)

所以我们只需要计算中间 \(B<x<B+l\) 的部分。而这部分数只有 \(l\) 个,预处理即可。

实际上做的时候其实是计算 \([p_1,p_2]\) 这个区间的数。其中 \(p_1\le B\le B+l\le p_2\)

总复杂度为 \(O(l\sqrt{n}\log(n)+T)\)


代码

#include <bits/stdc++.h>

using namespace std;

#define int long long

#define fileio(x,y) freopen(x,"r",stdin),freopen(y,"w",stdout)
#define tup tuple<int,int,int>
#define pii pair<int,int>
#define bit(x) bitset<x>
#define pb emplace_back
#define mt make_tuple
#define mp make_pair

const int   mod=998244353;
const int   maxn=1e6+10;

const int   L=400;

int a[maxn],f[maxn],s[maxn];
int b,p1,p2;

bool isp(int x) { for(int i=2; i<=sqrt(x); i++) if(!(x%i)) return false; return true; }
int phi(int x) { int tar=x; for(int i=2; i<=sqrt(x); i++) if(!(x%i)) { tar-=tar/i; while(!(x%i)) x/=i; } if(x>1) tar-=tar/x; return tar; }
int calc(int x,int maxx) { if(maxx<=0) return x; return calc(phi(x),maxx-1); }

void init()
{
    p1=b,p2=b+L;
    while(!isp(p1)) p1--;
    while(!isp(p2)) p2++;
    int maxx=0;
    for(int i=p1; i<=p2; i++)
    {
        maxx=max(maxx,phi(i));
        f[i-p1]=calc(i,maxx-b);
        s[i-p1]=(i>p1)*s[i-p1-1]+f[i-p1];
        // cerr<<"POS "<<i<<' '<<f[i-p1]<<' '<<phi(i)<<'\n';
    }
    return;
}

int solve(int x)
{
    if(x<p1) return x*(x+1)/2;
    if(x<=p2) return p1*(p1-1)/2+s[x-p1];
    return p1*(p1-1)/2+s[p2-p1]+x-p2;
}

void work()
{
    /* Code */
    int x,y; cin>>x>>y;
    cout<<solve(y)-solve(x-1)<<'\n';
    return;
}

signed main()
{
    // fileio("euler.in","euler.out");
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t;
    cin>>t>>b;
    init();
    while(t--)
        work();
    // for(int i=1; i<=10; i++) cerr<<solve(i)-solve(i-1)<<' '; cerr<<'\n';
    return 0;
} // Texas yyds !!!
posted @ 2024-08-05 12:39  静谧幽蓝  阅读(22)  评论(0编辑  收藏  举报