Description
有一张N×m的数表,其第i行第j列(1 < =i < =礼。1 < =j < =m)的数值为
能同一时候整除i和j的全部自然数之和。给定a,计算数表中不大于a的数之和。
Input
输入包括多组数据。
输入的第一行一个整数Q表示測试点内的数据组数,接下来Q行,每行三个整数n,m,a(|a| < =10^9)描写叙述一组数据。
Output
对每组数据,输出一行一个整数。表示答案模2^31的值。
Sample Input
2
4 4 3
10 10 5
Sample Output
20
148
HINT
1 < =N.m < =10^5 。 1 < =Q < =2×10^4
Source
Round 1 Day 1
在反演上的处理和DzyLovesMath1是相似的属于同一类题目
问题在于询问有10^4个所以要BIT维护一下前缀和
推公式过程懒得放了…贴个Po姐课件的图吧
(从未见过如此丧病的反演..反演还要加数据结构T_T
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 100010
#define lowbit(x) (x&(-x))
#define LL long long
#define MAXINT (0x7fffffff)
#define GET (ch>='0'&&ch<='9')
using namespace std;
int T,maxn;
int c[MAXN];
bool not_prime[MAXN];
int prime[MAXN],mu[MAXN]={0,1},top;
int ans[MAXN];
struct Query
{
int n,m,a,id;
bool operator <(const Query& t)const {return a<t.a;}
}q[MAXN];
struct num
{
int a,b;
bool operator <(const num& x)const {return a==x.a?b<x.b:a<x.a;}
}f[MAXN];
void init()
{
for (int i=2;i<=maxn;i++)
{
if (!not_prime[i]) prime[++top]=i,mu[i]=-1;
for (int j=1;j<=top&&i*prime[j]<=maxn;j++)
{
not_prime[i*prime[j]]=1;mu[i*prime[j]]=-mu[i];
if (i%prime[j]==0) {mu[i*prime[j]]=0;break;}
}
}
for (int i=1;i<=maxn;i++)
{
for (int j=i;j<=maxn;j+=i) f[j].a+=i;
f[i].b=i;
}
}
void add(int x,int delta) {for (int i=x;i<=maxn;i+=lowbit(i)) c[i]+=delta;}
int query(int x)
{
int ret=0;
for (int i=x;i;i-=lowbit(i)) ret+=c[i];
return ret;
}
void in(int &x)
{
char ch=getchar();x=0;int flag=1;
while (!GET) flag=(ch=='-')?
-1:1,ch=getchar();
while (GET) x=x*10+ch-'0',ch=getchar();x*=flag;
}
void calc(int x)
{
int id=q[x].id,n=q[x].n,m=q[x].m,last=0,t=min(n,m);
for (int i=1;i<=t;i=last+1)
{
last=min(n/(n/i),m/(m/i));
ans[id]+=(n/i)*(m/i)*(query(last)-query(i-1));
}
}
int main()
{
in(T);int now=0;
for (int i=1;i<=T;i++) in(q[i].n),in(q[i].m),in(q[i].a),q[i].id=i,maxn=max(maxn,max(q[i].n,q[i].m));
init();sort(q+1,q+T+1);sort(f+1,f+maxn+1);
for (int i=1;i<=T;i++)
{
while (now+1<=maxn&&f[now+1].a<=q[i].a)
{
now++;
for (int j=f[now].b;j<=maxn;j+=f[now].b) add(j,f[now].a*mu[j/f[now].b]);
}
calc(i);
}
for (int i=1;i<=T;i++) printf("%d\n",ans[i]&MAXINT);
}