先膜一发黄学长的题解,http://hzwer.com/4205.html
来一步步推
令a‘=a/d b‘=b/d
首先,原来要求的东西=
再利用莫比乌斯函数的性质可以得出
这里需要用到分块的思想,具体看程序里。
个人觉得(a/(a/i))非常妙
接下来问题就变成了一段段连续的了,
维护莫比乌斯函数的前缀和,就好了
1 #include<cstdio> 2 #include<algorithm> 3 #define ll long long 4 using namespace std; 5 const int maxn=50010; 6 const int N=50000; 7 int T,a,b,d,p; 8 int prime[maxn],mu[maxn]; 9 bool is_prime[maxn]; 10 void get_mu(){ 11 for (int i=0; i<=N; i++) is_prime[i]=true; 12 is_prime[0]=is_prime[1]=false; 13 mu[1]=1; 14 for (int i=2; i<=N; i++){ 15 if (is_prime[i]){ 16 prime[++p]=i; 17 mu[i]=-1; 18 } 19 for (int j=1; j<=p; j++){ 20 if (i*prime[j]>N) break; 21 is_prime[i*prime[j]]=false; 22 if (i % prime[j]==0) { 23 mu[i*prime[j]]=0; 24 break; 25 } 26 else mu[i*prime[j]]=-mu[i]; 27 } 28 } 29 for (int i=2; i<=N; i++) mu[i]+=mu[i-1]; 30 } 31 int solve(int a,int b){ 32 int res=0; 33 if (a>b) swap(a,b); 34 int pos=0; 35 for (int i=1; i<=a; i=pos+1){ 36 pos=min(a/(a/i),b/(b/i)); 37 res+=(mu[pos]-mu[i-1])*(a/i)*(b/i); 38 } 39 return res; 40 } 41 int main(){ 42 get_mu(); 43 scanf("%d",&T); 44 while (T--){ 45 scanf("%d%d%d",&a,&b,&d); 46 printf("%d\n",solve(a/d,b/d)); 47 } 48 return 0; 49 }
时间: 2024-10-13 11:42:56