luoguP3312 数表

智障如我

看题解看了半天才懂

其实就是一道莫比乌斯反演+离线处理+树状数组维护前缀和的题目

上代码

#include<bits/stdc++.h>
using namespace std;
namespace my_std
{
    typedef long long ll;
    typedef double db;
    const db PI=acos(-1.0);
    #define cp complex<db>
    #define MP make_pair
    #define fir first
    #define sec second
    #define fr(i,x,y) for(int i=(x);i<=(y);i++)
    #define pfr(i,x,y) for(int i=(y);i>=(x);i--)
    #define gfr(u) for(int i=head[u];i;i=e[i].nxt)
    #define pf printf
    //#define v e[i].to
    //#define w e[i].w
    inline ll read()
    {
        ll sum=0,f=1;
        char ch=0;
        while(!isdigit(ch))
        {
            if(ch=='-') f=-1;
            ch=getchar();
        }
        while(isdigit(ch))
        {
            sum=(sum<<1)+(sum<<3)+(ch^48);
            ch=getchar();
        }
        return sum*f;
    }
}
using namespace my_std;
const ll N=1e5+50;
int q,tmp,maxn,cnt,pri[100005],miu[100005],mark[N],tree[100005],ans[40005];
struct haha
{
    int n,m,a,id;
}ask[N];
pair<int,int> sig[100005];//约数和 
bool operator<(haha a,haha b)
{
    return a.a<b.a;
}
inline int lowbit(int x)
{
    return x&(-x);
}
inline void add(int x,int val)
{
    for(int i=x;i<=maxn;i+=lowbit(i)) tree[i]+=val;
}
inline int query(int x)
{
    int tmp=0;
    for(int i=x;i;i-=lowbit(i))
    {
        tmp+=tree[i];
    }
    return tmp;
}
inline void solve(int x)//dead
{
    int id=ask[x].id,n=ask[x].n,m=ask[x].m;
    for(int i=1,j;i<=ask[x].n;i=j+1)
    {
        j=min(n/(n/i),m/(m/i));
        //pf("alive before query\n");
        ans[id]+=(n/i)*(m/i)*(query(j)-query(i-1));
    }
}
inline void cal_miu()
{
    miu[1]=1;
    for(int i=2;i<=maxn;i++)
    {
        if(!mark[i]) pri[++cnt]=i,miu[i]=-1;
        for(int j=1;j<=cnt&&pri[j]*i<=maxn;j++)
        {
            mark[pri[j]*i]=1;
            if(i%pri[j]==0)
            {
                miu[pri[j]*i]=0;
                break;
            }
            else miu[pri[j]*i]=-miu[i];
        }
    }
}
inline void cal_sig()
{
    for(int i=1;i<=maxn;i++)
    {
        for(int j=i;j<=maxn;j+=i)
        {
            sig[j].first+=i; 
        } 
    } 
    for(int i=1;i<=maxn;i++)
    {
        sig[i].second=i;
    }
}
int main(void)
{
    q=read();
    for(int i=1;i<=q;i++)
    {
        ask[i].n=read(),ask[i].m=read(),ask[i].a=read(),ask[i].id=i;
        if(ask[i].n>ask[i].m) swap(ask[i].n,ask[i].m);
        maxn=max(maxn,ask[i].n);
    }
    cal_miu();
    cal_sig();
    sort(ask+1,ask+q+1);
    sort(sig+1,sig+maxn+1);
    for(int i=1;i<=q;i++)
    {
        while(tmp+1<=maxn&&sig[tmp+1].first<=ask[i].a)
        {
            tmp++;
            for(int j=sig[tmp].second;j<=maxn;j+=sig[tmp].second)
            {
                add(j,sig[tmp].first*miu[j/sig[tmp].second]);
            }
        }
        solve(i);
    }
    for(int i=1;i<=q;i++)
    {
        printf("%d\n",ans[i]&(~(1<<31)));
    }
    return 0;
}
上一篇:某拍sig算法揭秘---50行代码下载5000万小姐姐自拍小视频


下一篇:Linux 等待信号(sigsuspend)