神秘数论题:半完全幂
第一次见是在 gj 的 NOIP 模拟赛,但当时感觉太屎。前几天 gj 又在省选模拟赛中放了一次?比较疑惑。
题面
如果一个数可以被表示成 \(k\times a^b\)( \(b\ge2,k<a\)),那么称它为半幂数。求出 \(l\) 到 \(r\) 中半幂数个数。
\(l\le r\le 8\times10^{16}\)。
题解
为了版面下文的向下取整省略。
半幂数只用统计 \(b=2,3\) 的情况,因为 \(b\ge 4\) 可以用 \(b=2,3\) 的形式表示。如果 \(b\) 为偶数,则可以用 \(k\times (a^{b/2})^2\) 表示,如果 \(b\) 为奇数(\(b=2B+1\)),则可以用 \(ka\times (a^{B})^2\)。
计数可以使用差分,即求出 \(\le r\) 的方案数减去 \(\le l - 1\) 的方案数。设 \(f_k(x)=[x没有幂次为k的因数]\)。
考虑 \(b=2\) 的情况,方案数为
考虑 \(b=3\) 的情况,此时不能重复算到 \(b=2\)。探寻一下 \(k\times a^3\) 可以被 \(b=2\) 表示的条件,设 \(p^2\) 为 \(ak\) 最大平方因子,那么就可以表示为 \(\frac{ak}{p^2} \times (ap)^2\),合法仅当 \(\frac{ak}{p^2} \le ap\),即 \(k\le p^3\)。那么统计 \(b=3\) 时只用探寻 \(k>p^3\) 的情况即可。方案数即
设 \(g=\gcd(k,p^2)\),\(k_0=k/g\),\(p_0=p^2/g\)。式子变为
当 \(gcd(x,y)=1\) 时,\(f_2(xy)=f_2(x)f_2(y)\),式子变为
设 \(S_d(n)=\sum_{i=1}^n f_2(di)\),式子变为
时间复杂度 \(O(n^{1/3}\log n)\)。
code
#pragma GCC optimize(3, "Ofast", "inline")
#include<cstdio>
#include<vector>
#define N 1000010
#define MAXN 500000
#define ll long long
using namespace std;
int isp[N], pri[N], mu[N], fzh[N], tot = 0;
int ch2[N];
vector<int>s[N], d[N];
ll sq2(ll x) { ll ml = 0, mr = 1e9; while(ml < mr) { ll mid = (ml + mr + 1) / 2; if(mid * mid <= x)ml = mid; else mr = mid - 1; } return ml; }
ll sq3(ll x) { ll ml = 0, mr = 1e6; while(ml < mr) { ll mid = (ml + mr + 1) / 2; if(mid * mid * mid <= x)ml = mid; else mr = mid - 1; } return ml; }
ll sq4(ll x) { ll ml = 0, mr = 2e4; while(ml < mr) { ll mid = (ml + mr + 1) / 2; if(mid * mid * mid * mid <= x)ml = mid; else mr = mid - 1; } return ml; }
int ch(int x, int k)
{
while(x > 1)
{
int d = fzh[x], s = 0;
while(x % d == 0)
{
x /= d;
s++;
}
if(s >= k)return 0;
}
return 1;
}
void init()
{
mu[1] = 1;
for(ll i = 2; i <= MAXN; i++)
{
if(!isp[i])
{
pri[++tot] = i;
mu[i] = -1;
fzh[i] = i;
}
for(int j = 1; j <= tot && i * pri[j] <= MAXN; j++)
{
int v = i * pri[j];
isp[v] = 1;
fzh[v] = pri[j];
if(i % pri[j] == 0)
{
mu[v] = 0;
break;
}
mu[v] = -mu[i];
}
}
for(int i = 1; i <= MAXN; i++)ch2[i] = ch(i, 2);
for(int i = 1; i <= MAXN; i++)
{
s[i].push_back(0);
for(int j = 1; i * j <= MAXN; j++)
{
d[i * j].push_back(i);
s[i].push_back(s[i][j - 1] + ch2[i * j]);
}
}
}
ll gcd(ll a, ll b)
{
if(b == 0)return a;
return gcd(b, a % b);
}
ll query(ll x)
{
if(!x)return 0;
ll ans = 0, sq3x = sq3(x);
for(ll a = 1; a <= sq3x; a++)
if(ch(a, 2))
{
ans += sq2(x / a) - a;
}
ll sq4x = sq4(x);
for(ll a = 1; a <= sq4x; a++)
if(ch(a, 3))
{
ll sq3a = sq3(a);
for(ll k = 1; k <= sq3a; k++)
{
ll g = gcd(a, k * k), ap = a / g, kp = k * k / g;
if(ch(ap, 2))
{
for(int dd : d[ap])
ans += mu[dd] * (s[dd][sq3(x / a) / kp / dd] - s[dd][(a - 1) / kp / dd]);
}
}
}
return ans;
}
void slove()
{
ll l, r;
scanf("%lld%lld", &l, &r);
printf("%lld\n", query(r) - query(l - 1));
}
int main()
{
init();
int t;
scanf("%d", &t);
while(t--)slove();
return 0;
}

浙公网安备 33010602011771号