Time Limit: 10 Sec Memory Limit: 512 MB
Description
Input
Output
Sample Input
10 10
100 100
Sample Output
2791
HINT
T = 10000
N, M <= 10000000
Solution
枚举质数p,答案即为$sum_{p}sum_{i=1}^{left lfloor n/p ight floor}sum_{j=1}^{left lfloor m/p ight floor}left [ gcd(i,j)=1 ight ]=sum_{p}sum_{i=1}^{left lfloor n/p ight floor}sum_{j=1}^{left lfloor m/p ight floor}sum_{d|i,d|j}mu (d)$
考虑每个d,则原式等于$sum_{p}sum_{d=1}^{leftlfloor min(n,m)/p ight floor}leftlfloor frac{n}{pd} ight floor leftlfloor frac{m}{pd} ight floor mu (d)$
令k=pd,得到$sum_{k=1}^{min(n,m)}leftlfloor frac{n}{k} ight floor leftlfloor frac{m}{k} ight floor sum_{p|k}mu(frac{k}{p})$
用筛法可以预处理出每个k对应的$sum_{p|k}mu(frac{k}{p})$,前缀和后利用$leftlfloor frac{n}{k} ight floor leftlfloor frac{m}{k} ight floor$只有$O(sqrt{n})$种取值,我们可以在$O(sqrt{n})$的时间内计算每次询问,总复杂度$O(n+Tsqrt{n})$。
Code
#include<cstdio> #include<algorithm> using namespace std; #define ll long long inline int read() { int x;char c; while((c=getchar())<'0'||c>'9'); for(x=c-'0';(c=getchar())>='0'&&c<='9';)x=(x<<3)+(x<<1)+c-'0'; return x; } #define MN 10000000 int mu[MN+5],p[MN+5],pn; ll f[MN+5]; bool u[MN+5]; int main() { int T=read(),n,m,i,j;ll ans; for(mu[1]=1,i=2;i<=MN;++i) { if(!u[i])p[++pn]=i,mu[i]=-1; for(j=1;i*p[j]<=MN&&(u[i*p[j]]=1);++j) if(i%p[j])mu[i*p[j]]=-mu[i];else break; } for(i=1;i<=pn;++i)for(j=1;j*p[i]<=MN;++j)f[j*p[i]]+=mu[j]; for(i=1;i<=MN;++i)f[i]+=f[i-1]; while(T--) { n=read();m=read();ans=0; for(i=1;i<=n&&i<=m;i=j+1)j=min(n/(n/i),m/(m/i)),ans+=(f[j]-f[i-1])*(n/i)*(m/i); printf("%lld ",ans); } }