T168866

无聊的题目

大师的嘲讽

感觉很高妙,果然我什么都不会。

我给洛谷送了这么多钱,看一道去年省选计划的题不过分吧。。。

题面描述:

对 $ n = p _ 1 ^ { a _ 1 } p _ 2 ^ { a _ 2 } \cdots p _ k ^ { a _ k }$,定义:

$$ f ( n ) = \min \{ a _ 1 , a _ 2 , \cdots , a _ k\} \times \max \{ a _ 1 , a _ 2 , \cdots , a _ k \}$$

特别地,规定 $ f ( 1 ) = 0$,求:

$$ \sum _ { i = 1 } ^ { n } f ( i )$$

数据范围:$ n \le 10 ^ { 1 2 }$。


设满足 $\max \{ a _ 1 , \cdots , a _ k\} = v$ 的数 $x$ 的个数为 $f(v)$。

设满足 $\max \{ a _ 1 , \cdots , a _ k\} \le v$ 的数 $x$ 的个数为 $g(v)$。

可以知道 $f ( v )= g ( v ) - g( v - 1 )$。

然后我们的 $g ( v ) $ 可以容斥计算:

$$g ( v ) = \sum _ { d = 1 } \mu ( d ) \left\lfloor \dfrac {n} {d ^ { v + 1 }} \right\rfloor$$

意义不解释。。。

然后就有了 $f(v)$。

接着暴力枚举 $\min \ge 2 $ 的数。

具体做法是筛出 $\sqrt{n}$ 内的质数,暴力枚举质数指数的所有排列组合,并且保证没有一个数的指数为 1,很容易证明,这个复杂度是 $O(\sqrt{n}\log n)$ 的,这一部分的答案就这么解决了。并且记得在过程中把统计过的 $f( \max )$ 给减掉。

剩下的全都是 $\min = 1 $ 的数,那么只和 $\max$ 有关了,直接统计即可。

至于拓展到二元函数(不仅仅是乘法,任何复杂度较低的运算)情况,也都是如此。

时间复杂度是 $O(\sqrt { n} \log n)$ 的。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include<iostream>
#include<cstdio>
#define ll __int128
using namespace std;
namespace Ehnaev{
inline ll read() {
ll ret=0,f=1;char ch=getchar();
while(ch<48||ch>57) {if(ch==45) f=-f;ch=getchar();}
while(ch>=48&&ch<=57) {ret=(ret<<3)+(ret<<1)+ch-48;ch=getchar();}
return ret*f;
}
inline void write(ll x) {
static char buf[22];static ll len=-1;
if(x>=0) {do{buf[++len]=x%10+48;x/=10;}while(x);}
else {putchar(45);do{buf[++len]=-(x%10)+48;x/=10;}while(x);}
while(len>=0) putchar(buf[len--]);
}
}using Ehnaev::read;using Ehnaev::write;

const ll N=2e6,inf=3200;

ll n,cnt,ans;
ll prime[N+5],mu[N+5],g[N+5],f[N+5];
bool ff[N+5];

inline void Init() {
ff[1]=1;mu[1]=1;
for(ll i=2;i<=N;i++) {
if(!ff[i]) {prime[++cnt]=i;mu[i]=-1;}
for(ll j=1;j<=cnt&&prime[j]*i<=N;j++) {
ff[i*prime[j]]=1;
if(i%prime[j]==0) {mu[i*prime[j]]=0;break;}
mu[i*prime[j]]=-mu[i];
}
}
}

inline void Dfs(ll x,ll step,ll ma,ll mi) {
// printf("step=");write(step);putchar(10);
if(x*prime[step]*prime[step]>n) return;
Dfs(x,step+1,ma,mi);x=x*prime[step];if(x>n) return;
for(ll i=2;x<=n;i++) {
x=x*prime[step];if(x>n) return;
ll tmpma=max(ma,i),tmpmi=min(mi,i);
ans+=tmpma*tmpmi;f[tmpma]--;
Dfs(x,step+1,max(ma,i),min(mi,i));
}
}

inline ll Pow(ll b,ll p) {
ll r=1;while(p) {if(p&1) r=r*b;b=b*b;p>>=1;}return r;
}

int main() {

n=read();Init();

g[0]=1;f[0]=1;
for(ll v=1;v<=40;v++) {
for(ll i=1;i<=n;i++) {
ll tmp=Pow(i,v+1);if(tmp>n) break;
g[v]+=mu[i]*(n/tmp);
}
f[v]=g[v]-g[v-1];
}

Dfs(1,1,0,inf);

for(ll i=1;i<=40;i++) ans+=f[i]*i;

write(ans);

return 0;
}