神犇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