BZOJ 3529 数表

Posted on 2016-10-28 20:23  ziliuziliu  阅读(112)  评论(0编辑  收藏  举报

莫比乌斯反演+BIT。

因为答案没有排序而调了很久。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 100000
#define mod 2147483647LL
using namespace std;
int tt,n,m,miu[maxn+50],prime[maxn/10],top=0,t[maxn+50],f1[maxn+50],f2[maxn+50],ans[maxn],pos=1;
bool vis[maxn+50];
struct f_
{
    int val,id;
}f[maxn+50];
struct query
{
    int n,m,a,id;
}q[maxn];
bool cmp1(f_ x,f_ y)
{
    return x.val<y.val;
}
bool cmp2(query x,query y)
{
    return x.a<y.a;
}
void get_table()
{
    miu[1]=f1[1]=f2[1]=1;
    for (int i=2;i<=maxn;i++)
    {
        if (!vis[i])
        {
            prime[++top]=i;
            miu[i]=-1;f1[i]=1;f2[i]=i+1;
        }
        for (int j=1;j<=top && i*prime[j]<=maxn;j++)
        {
            vis[i*prime[j]]=true;
            if (i%prime[j])
            {
                miu[i*prime[j]]=-miu[i];
                f1[i*prime[j]]=(f1[i]*f2[i])&mod;f2[i*prime[j]]=(prime[j]+1)&mod;
            }
            else
            {
                miu[i*prime[j]]=0;
                f1[i*prime[j]]=f1[i]&mod;f2[i*prime[j]]=(((f2[i]*prime[j])&mod)+1)&mod;
                break;
            }
        }
    }
    for (int i=1;i<=maxn;i++)
    {
        f[i].id=i;
        f[i].val=(f1[i]*f2[i])&mod;
    }
}
int lowbit(int x) {return (x&(-x));}
void modify(int x,int val)
{
    for (int i=x;i<=maxn;i+=lowbit(i))
    {
        t[i]=(t[i]+val)&mod;
        if (t[i]<0) t[i]=(t[i]+mod+1)&mod;
    }
}
int ask(int x)
{
    int ret=0;
    for (int i=x;i>=1;i-=lowbit(i))
        ret=(ret+t[i])&mod;
    return ret;
}
void work(int x)
{
    int l=1,r,ret=0;
    int n=q[x].n,m=q[x].m;
    if (n>m) swap(n,m);
    while (l<=n)
    {
        r=min(n/(n/l),m/(m/l));
        ret=(ret+((((n/l)*(m/l))&mod)*(ask(r)-ask(l-1)+mod+1))&mod)&mod;
        l=r+1;
    }
    ans[q[x].id]=ret;
}
int main()
{
    get_table();
    scanf("%d",&tt);
    for (int i=1;i<=tt;i++)
    {
        scanf("%d%d%d",&q[i].n,&q[i].m,&q[i].a);
        q[i].id=i;
    }
    sort(f+1,f+maxn+1,cmp1);
    sort(q+1,q+tt+1,cmp2);
    for (int i=1;i<=tt;i++)
    {
        int j;
        for (j=pos;j<=maxn;j++)
        {
            if (f[j].val>q[i].a) break;
            for (int k=1;k*f[j].id<=maxn;k++)
                modify(k*f[j].id,f[j].val*miu[k]);
        }
        pos=j;
        work(i);
    }
    for (int i=1;i<=tt;i++) printf("%d\n",ans[i]);
    return 0;
}