[积性函数]DIVCNT2 - Counting Divisors (square)

http://www.spoj.com/problems/DIVCNT2/

sol:

考虑到i^2这个东西有点恶心
w(x)表示x的不同的质因子个数
d|i21=d|i2w(d)实际上就是i的所有约数的质因子的幂是否加上i的对应质因子的幂,这样就成为了i^2的约数了。
考虑到2w(d)的实际意义是1到d的无平方因子的个数。这个东西等价于
d|iq|dμ(q)2
这个东西就很有意思了,他长这样
11μ2
(11)μ2
d(x)表示x的除数函数
就是dμ2
inq|iμ(q)2d(iq)
qnμ(q)2inqd(i)
2个东西预处理前1e6项,复杂度为O(23)
对于前面那个当他的n很大的时候,可以这么暴力算
iddi2μ(i)
实际上就是用1的倍数-1个质数的平方数+2个质数的平方数这样容斥,容易注意到他的容斥系数和mu的定义一样。
后面那个东西实际上就是
inni
当n很大的时候,暴力分块也可以做到更号
直接暴力做是O(34)

#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);
    }
}
阅读更多
版权声明:他无力阻止你的转载 https://blog.csdn.net/qq_36993218/article/details/79882985
个人分类: 积性函数
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭