传送门
传送门
题意:
TTT组询问给定n,m,an,m,an,m,a,求
∑i=1N∑j=1M[(∑d∈N∗[d∣i][d∣j]d)≤a]∑d∈N∗[d∣i][d∣j]d\sum_{i=1}^{N}\sum_{j=1}^{M}[(\sum_{d \in N^*}[d\mid i][d \mid j]d)\leq a]\sum_{d \in N^*}[d\mid i][d \mid j]di=1∑Nj=1∑M[(d∈N∗∑[d∣i][d∣j]d)≤a]d∈N∗∑[d∣i][d∣j]d
1≤n,m≤1e5,1≤a≤1e9,1≤T≤2e41 \leq n,m \leq 1e5,1 \leq a \leq1e9,1 \leq T \leq2e41≤n,m≤1e5,1≤a≤1e9,1≤T≤2e4
对2312^{31}231取模
反演神题
假设没有前面的限制
∑i=1N∑j=1M∑d∈N∗[d∣i][d∣j]\sum_{i=1}^{N}\sum_{j=1}^{M}\sum_{d \in N^*}[d\mid i][d \mid j]i=1∑Nj=1∑Md∈N∗∑[d∣i][d∣j]
记F(x)F(x)F(x)表示约数和
∑i=1N∑j=1MF(gcd(i,j))\sum_{i=1}^N\sum_{j=1}^{M}F(gcd(i,j))i=1∑Nj=1∑MF(gcd(i,j))
套路性地枚举gcdgcdgcd
∑d∑i=1N∑j=1M[gcd(i,j)=d]F(d)\sum_{d}\sum_{i=1}^N\sum_{j=1}^{M}[gcd(i,j)=d]F(d)d∑i=1∑Nj=1∑M[gcd(i,j)=d]F(d)
套路性地提到前面
∑dF(d)∑i=1n∑j=1m[gcd(i,j)=d]\sum_{d}F(d)\sum_{i=1}^n\sum_{j=1}^{m}[gcd(i,j)=d]d∑F(d)i=1∑nj=1∑m[gcd(i,j)=d]
后面是个套路性的反演
设
f(d)=∑i=1N∑j=1M[gcd(i,j)=d]f(d)=\sum_{i=1}^N\sum_{j=1}^{M}[gcd(i,j)=d]f(d)=i=1∑Nj=1∑M[gcd(i,j)=d]
g(d)=∑d∣nf(n)=⌊Nd⌋⌊Md⌋g(d)=\sum_{d\mid n}f(n)=\lfloor\frac{N}{d}\rfloor\lfloor\frac{M}{d}\rfloorg(d)=d∣n∑f(n)=⌊dN⌋⌊dM⌋
f(d)=∑d∣ng(n)μ(nd)=∑d∣n⌊Nn⌋⌊Mn⌋μ(nd)f(d)=\sum_{d\mid n}g(n)\mu(\frac{n}{d})=\sum_{d \mid n}\lfloor\frac{N}{n}\rfloor\lfloor\frac{M}{n}\rfloor\mu(\frac{n}{d})f(d)=d∣n∑g(n)μ(dn)=d∣n∑⌊nN⌋⌊nM⌋μ(dn)
代回去
∑dF(d)∑d∣n⌊Nn⌋⌊Mn⌋μ(nd)\sum_{d}F(d)\sum_{d \mid n}\lfloor\frac{N}{n}\rfloor\lfloor\frac{M}{n}\rfloor\mu(\frac{n}{d})d∑F(d)d∣n∑⌊nN⌋⌊nM⌋μ(dn)
∑n=1min(N,M)⌊Nn⌋⌊Mn⌋∑d∣nF(d)μ(nd)\sum_{n=1}^{min(N,M)}\lfloor\frac{N}{n}\rfloor\lfloor\frac{M}{n}\rfloor\sum_{d\mid n}F(d)\mu(\frac{n}{d})n=1∑min(N,M)⌊nN⌋⌊nM⌋d∣n∑F(d)μ(dn)
左边是个套路性的整除分块 不管
右边并没有很好的性质,只能筛出来暴力求……
等下,原题是有限制F(d)≤aF(d)\leq aF(d)≤a的
设
G(n)=∑d∣nF(d)μ(nd)G(n)=\sum_{d\mid n}F(d)\mu(\frac{n}{d})G(n)=d∣n∑F(d)μ(dn)
我们发现只有不超过aaa的F(d)F(d)F(d)才对答案有贡献
而T,NT,NT,N都很小
所以可以把F(d)F(d)F(d)和aaa排个序,拿个指针指一下
跑到一个aaa把前面的F(d)F(d)F(d)枚举倍数统计更新GGG,再拿整除分块算答案
需要维护单点加,区间询问,用个树状数组即可
复杂度大概O(NlogN+TlogTT)O(NlogN+TlogT\sqrt{T})O(NlogN+TlogTT)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
#define MAXN 100005
using namespace std;
const int N=100000;
int np[MAXN],pl[MAXN],cnt;
int mu[MAXN],f[MAXN],mp[MAXN],pt[MAXN];
inline int qpow(int a,int p)
{int ans=1;while (p){if (p&1) ans*=a;a*=a;p>>=1;}return ans;
}
void init()
{np[1]=mu[1]=f[1]=1;for (int i=2;i<=N;++i){if (!np[i]){pl[++cnt]=i;mu[i]=-1;mp[i]=i;pt[i]=1;}int x;for (int j=1;(x=i*pl[j])<=N;++j){np[x]=1;mp[x]=pl[j];if (i%pl[j]==0){mu[x]=0;pt[x]=pt[i]+1;break;}mu[x]=-mu[i];pt[x]=1;}}for (int i=2;i<=N;i++){int t=qpow(mp[i],pt[i]);if (i==t) f[i]=f[i/mp[i]]+t;else f[i]=f[t]*f[i/t];}
}
int p[MAXN];
inline bool cmp(const int& a,const int& b){return f[a]<f[b];}
struct query{int n,m,a,id;}q[MAXN];
inline bool operator <(const query& x,const query& y){return x.a<y.a;}
struct BIT
{int s[MAXN];inline int lowbit(const int& x){return x&-x;}inline void modify(int x,const int& v){for (;x<=N;s[x]+=v,x+=lowbit(x));}inline int query(int x){int ans=0;for (;x;ans+=s[x],x-=lowbit(x));return ans;}
}g;
int res[MAXN];
//int calc(int x,int y,int a)
//{
// int ans=0;
// for (int i=1;i<=x&&i<=y;i++)
// if (x%i==0&&y%i==0)
// ans+=i;
// if (ans<=a) return ans;
// else return 0;
//}
int main()
{init();for (int i=1;i<=N;i++) p[i]=i;sort(p+1,p+N+1,cmp);int pos=0;int T;scanf("%d",&T);for (int i=1;i<=T;i++) {scanf("%d%d%d",&q[i].n,&q[i].m,&q[i].a);q[i].id=i;
// int t=0;
// for (int x=1;x<=q[i].n;x++)
// for (int y=1;y<=q[i].m;y++)
// t+=calc(x,y,q[i].a);
// printf("%d\n",t&(~(1<<31)));}sort(q+1,q+T+1);for (int i=1;i<=T;i++){while (pos<N&&f[p[pos+1]]<=q[i].a){++pos;for (int d=1;d*p[pos]<=N;++d) g.modify(d*p[pos],f[p[pos]]*mu[d]);}if (q[i].n>q[i].m) swap(q[i].n,q[i].m);int ans=0;for (int l=1,r;l<=q[i].n;l=r+1){r=min(q[i].n/(q[i].n/l),q[i].m/(q[i].m/l));ans+=(q[i].n/l)*(q[i].m/l)*(g.query(r)-g.query(l-1));}res[q[i].id]=ans;}for (int i=1;i<=T;i++) printf("%d\n",res[i]&(~(1<<31)));return 0;
}