YY的GCD

神犇YY虐完数论后给傻×kAc出了一题
给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对
kAc这种傻×必然不会了,于是向你来请教……
多组输入

输入描述 Input Description

第一行一个整数 T 表述数据组数接下来T行,每行两个正整数,表示N.M;

数据范围:

T = 10000
N, M <= 10000000

思路:莫比乌斯反演:

转自http://blog.csdn.net/cuso45h20/article/details/51644194

 1 #include<stdio.h>
 2 #include<algorithm>
 3 #include<queue>
 4 #include<stdlib.h>
 5 #include<iostream>
 6 #include<string.h>
 7 using namespace std;
 8 typedef long long LL;
 9 bool prime[10000005];
10 int ak[10000005];
11 LL mul[10000005];
12 LL c[10000005];
13 int main(void)
14 {
15     int cn = 0;
16     mul[1] = 1;
17     for(int i = 2; i <= 10000000; i++)
18     {
19         if(!prime[i])
20         {
21             ak[cn++] = i;
22             mul[i] = -1;
23         }
24         for(int j = 0; j < cn&&(LL)ak[j]*i<=10000000; j++)
25         {
26             if(i%ak[j])
27             {
28                 prime[i*ak[j]] = true;
29                 mul[i*ak[j]] = -mul[i];
30             }
31             else
32             {
33                 prime[i*ak[j]] = true;
34                 mul[i*ak[j]] = 0;
35                 break;
36             }
37         }
38     }
39     int T;
40     for(int i = 2;i <= 10000000;i++)
41     {   if(!prime[i])
42         for(int j = 1;(i*j) <= 10000000;j++)
43         {
44             c[i*j] += mul[j];
45         }
46     }
47     for(int i = 2;i <= 10000000;i++)
48         c[i] += c[i-1];
49     scanf("%d",&T);
50     while(T--)
51     {
52         int n,m;
53         scanf("%d %d",&n,&m);
54         LL sum = 0;
55         for(int i = 1;i <= min(n,m);)
56         {
57             LL x = n/i;
58             LL y = m/i;
59             int j = min(n/x,m/y);
60             sum = sum + (c[j] - c[i-1])*(x*y);
61             i = j+1;
62         }
63         printf("%lld
",sum);
64     }
65     return 0;
66 }

N,M

原文地址:https://www.cnblogs.com/zzuli2sjy/p/6394046.html