P2257 YY的GCD

P2257 YY的GCD

题目描述

神犇YY虐完数论后给傻×kAc出了一题

给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对

kAc这种傻×必然不会了,于是向你来请教……

多组输入

输入输出格式

输入格式:

 

第一行一个整数T 表述数据组数

接下来T行,每行两个正整数,表示N, M

 

输出格式:

 

T行,每行一个整数表示第i组数据的结果

 

输入输出样例

输入样例#1: 复制
2
10 10
100 100
输出样例#1: 复制
30
2791

说明

T = 10000

N, M <= 10000000

思路:倍数莫比乌斯反演。

(太长时间没写字了。。 

 

代码:

 1 #include<bits/stdc++.h>
 2 #define  ll long long
 3 using namespace std;
 4 const int N = 1e7 + 5;
 5 int t;
 6 //线性筛法求莫比乌斯函数
 7 bool vis[N + 10];
 8 int pri[N + 10];
 9 int mu[N + 10];
10 ll sum[N];
11 int f[N];
12 void mus() {
13     memset(vis, 0, sizeof(vis));
14     memset(f,0, sizeof(f));//f[n]=sum(mu[n/p])
15     mu[1] = 1;
16     int tot = 0;
17     for (int i = 2; i < N; i++) {
18         if (!vis[i]) {
19             pri[tot++] = i;
20             mu[i] = -1;
21         }
22         for (int j = 0; j < tot && i * pri[j] < N; j++) {
23             vis[i * pri[j]] = 1;
24             if (i % pri[j] == 0) {
25                 mu[i * pri[j]] = 0;
26                 break;
27             }
28             else  mu[i * pri[j]] = -mu[i];
29         }
30     }
31     for(int i=1;i<N;i++)
32         for(int j=0;j<tot&&pri[j]*i<N;j++) f[i*pri[j]]+=mu[i];//需要重复更新,不能放在线性筛内部
33     sum[1]=0;
34     for(int i=2;i<N;i++) sum[i]=sum[i-1]+f[i];
35 }
36 int n,m,k;
37 ll cal(int x,int y){
38     int ma=min(x,y);
39     ll res=0;
40     for(int i=1,j;i<=ma;i=j+1){
41         j=min(x/(x/i),y/(y/i));
42         if(j>=ma) j=ma;
43         res+=1ll*(sum[j]-sum[i-1])*(x/i)*(y/i);
44     }
45     return res;
46 }
47 
48 int main() {
49     mus();
50     scanf("%d",&t);
51     for(int i=1;i<=t;i++){
52         scanf("%d%d",&n,&m);
53         ll ans;
54         ans=cal(n,m);
55         printf("%lld\n",ans);
56     }
57     return 0;
58 }

 

posted @ 2018-09-02 17:16  thges  阅读(143)  评论(0编辑  收藏  举报