http://www.spoj.com/problems/DIVCNT2/
sol:
考慮到i^2這個東西有點噁心
w(x)表示x的不同的質因子個數
實際上就是i的所有約數的質因子的冪是否加上i的對應質因子的冪,這樣就成爲了i^2的約數了。
考慮到 的實際意義是1到d的無平方因子的個數。這個東西等價於
這個東西就很有意思了,他長這樣
d(x)表示x的除數函數
就是
2個東西預處理前1e6項,複雜度爲
對於前面那個當他的n很大的時候,可以這麼暴力算
實際上就是用1的倍數-1個質數的平方數+2個質數的平方數這樣容斥,容易注意到他的容斥係數和mu的定義一樣。
後面那個東西實際上就是
當n很大的時候,暴力分塊也可以做到更號
直接暴力做是 的
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
using namespace std;
typedef long long ll;
typedef double db;
int n,m;
inline int read()
{
char c;
int res,flag=0;
while((c=getchar())>'9'||c<'0') if(c=='-')flag=1;
res=c-'0';
while((c=getchar())>='0'&&c<='9') res=(res<<3)+(res<<1)+c-'0';
return flag?-res:res;
}
const int N=1e6+7;
const int M=1e6;
ll a[N],b[N];
int c[N],prime[N];
bool is[N];
inline ll calc1(int x)
{
if(x<=M) return a[x];
int y=sqrt(x);
ll ans=0;
for(int i=1;i<=y;++i)
ans+=x/i/i*c[i];
return ans;
}
inline ll calc2(int x)
{
if(x<=M) return b[x];
ll ans=0;
int z,zz;
for(int i=1;i<=x;++i)
{
z=x/i;
zz=x/z;
ans+=(zz-i+1)*z;
i=zz;
}
return ans;
}
int main()
{
// freopen("function.in","r",stdin);
// freopen("function.out","w",stdout);
n=1000000;
b[1]=1;
for(int i=2;i<=n;++i)
for(int j=1;i*j<=n;++j)
b[i*j]++;
for(int i=2;i<=n;++i)
{
b[i]++;
b[i]=b[i]+b[i-1];
}
c[1]=1;
a[1]=1;
for(int i=2;i<=n;++i)
{
if(!is[i]) prime[++prime[0]]=i,c[i]=-1;
for(int j=1;j<=prime[0]&&i*prime[j]<=n;++j)
{
is[i*prime[j]]=1;
if(!(i%prime[j]))
{
c[i*prime[j]]=0;
break;
}
c[i*prime[j]]=-c[i];
}
a[i]=a[i-1]+(c[i]!=0);
}
m=read();
while(m--)
{
n=read();
int z,zz;
ll ans=0;
for(int i=1;i<=n;++i)
{
z=n/i;
zz=n/z;
ans+=(calc1(zz)-calc1(i-1))*calc2(z);
i=zz;
}
printf("%lld\n",ans);
}
}