智障如我
看题解看了半天才懂
其实就是一道莫比乌斯反演+离线处理+树状数组维护前缀和的题目
上代码
#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;
}