题解 P4466 【[国家集训队]和与积】
前置知识:莫比乌斯反演
算是一道相对基础的反演题了吧。。
求有多少组
由于
首先是一个很显然的结论:若
为什么呢?因为此时
所以
所以我们可以设
因为
所以这道题也就是求
推推式子吧:
套一个莫比乌斯函数的基本操作
设
枚举了
代码如下:
#include<cmath>
#include<cstdio>
#include<algorithm>
typedef long long ll;
const int N=1e5+5;
bool b[N];
int p[N],u[N];
ll calc(int x,int y){
ll a=0;int z=x<<1;
if(!y) return 0;
for(int i=x+1;i<z;i=x+1){
if(!(y/i)) return a;
x=std::min(y/(y/i),z-1);
a+=(x-i+1)*(y/i);
}
return a;
}
int main(){
int t=0,n,m,x;ll a=0;
scanf("%d",&n);
m=sqrt(n);
u[1]=1;
for(int i=2;i<=m;++i){
if(!b[i]) p[++t]=i,u[i]=-1;
for(int j=1;j<=t && (x=i*p[j])<=m;++j){
b[x]=1,u[x]=-u[i];
if(!(i%p[j])){u[x]=0;break;}
}
}
for(int i=1;i<=m;++i){
if(!u[i]) continue;
for(int j=1;j*i<=m;++j)
a+=u[i]*calc(j,n/(i*i*j));
}
printf("%lld\n",a);
return 0;
}
时间复杂度我感觉是最多
不过洛咕上有大神证出了是