SPOJ-PGCD Primes in GCD Table

题目链接:https://vjudge.net/problem/SPOJ-PGCD

题目大意:

  给定 \(N\) 和 \(M\),求满足 \((1 \le x \le N), (1 \le y \le M)\),且 \(gcd(x,y)\) 为素数的 \((x,y)\) 的对数。

知识点:  莫比乌斯反演

解题思路:

  设 \(g(p)\) 表示满足 \((1 \le x \le N), (1 \le y \le M)\),且 \(gcd(x,y) = p\) 的 \((x,y)\) 的对数。直接求 \(g(p)\) 是不可行的,其时间复杂度为 \(O(NM)\).

  再设 \(f(p)\) 表示满足 \((1 \le x \le N), (1 \le y \le M)\),且 \(p|gcd(x,y)\) 的 \((x,y)\) 的对数,易知 \(f(p)=(N/p)*(M/p)\)。且不难推出 \(f(n) = \sum \limits_{n|d} g(d)\).    \((1)\)

  莫比乌斯反演公式:若满足 \(F(n) = \sum \limits_{n|d} f(d)\),则有 \(f(n) = \sum \limits_{n|d} \mu(\frac{d}{n})F(d)\).

  将其代入式 \((1)\) 得:

  \(g(n) = \sum \limits_{n|d} \mu(\frac{d}{n})f(d) = \sum \limits_{n|d} \mu(\frac{d}{n})(N/d)(M/d)\)  \((2)\)

  最终的答案为(\(p\) 代表质数):

  \(\sum \limits_{p} g(p) = \sum \limits_{p} \sum \limits_{p|d} \mu(\frac{d}{p})(N/d)(M/d)\)

      \(= \sum \limits_{d}^{min(M,N)} (N/d)(M/d) \sum \limits_{p|d} \mu(\frac{d}{p})\)  \((3)\)

第二个求和函数可以预处理,枚举每一个质数,更新对应的前缀和。

AC代码:

 1 #include <bits/stdc++.h>
 2
 3 using namespace std;
 4 typedef long long LL;
 5 const int maxn = 1e7+5;
 6 bool check[maxn];
 7 int prime[maxn],Mobius[maxn];
 8 int tot;
 9 int u[maxn];
10
11 void init(){
12     Mobius[1]=1;
13     tot=0;
14     for(int i=2;i<maxn;i++){
15         if(!check[i]){
16             prime[tot++]=i;
17             Mobius[i]=-1;
18         }
19         for(int j=0;j<tot&&i*prime[j]<maxn;j++){
20             check[i*prime[j]]=true;
21             if(i%prime[j]==0){
22                 Mobius[i*prime[j]]=0;
23                 break;
24             } else
25                 Mobius[i*prime[j]]=-Mobius[i];
26         }
27     }
28     for(int i=0;i<tot;i++){
29         for(int j=prime[i];j<maxn;j+=prime[i]){
30             u[j]+=Mobius[j/prime[i]];   // u[j] 代表分子为 j(对应式3中的d) 的和函数的值
31         }
32     }
33     for(int i=1;i<maxn;i++) u[i]+=u[i-1];   //处理出前缀和
34 }
35 int main(){
36     init();
37     int t,n,m;
38     scanf("%d",&t);
39     while(t--){
40         LL ans=0;
41         int last;
42         scanf("%d%d",&n,&m);
43         for(int i=1;i<=min(n,m);i=last+1){
44             last=min(n/(n/i),m/(m/i));  // [i,last] 这一段的 u[] 对应 (N/d)(M/d) 相等,不难用实验验证
45             ans+=(LL)(n/i)*(m/i)*(u[last]-u[i-1]);
46         }
47         printf("%lld\n",ans);
48     }
49     return 0;
50 }

     

  

原文地址:https://www.cnblogs.com/Blogggggg/p/8954320.html

时间: 2024-10-10 19:36:20

SPOJ-PGCD Primes in GCD Table的相关文章

SPOJ PGCD - Primes in GCD Table (好题! 莫比乌斯反演+分块求和优化)

PGCD - Primes in GCD Table Johnny has created a table which encodes the results of some operation -- a function of two arguments. But instead of a boring multiplication table of the sort you learn by heart at prep-school, he has created a GCD (greate

SPOJ - PGCD Primes in GCD Table(莫比乌斯反演)

http://www.spoj.com/problems/PGCD/en/ 题意: 给出a,b区间,求该区间内满足gcd(x,y)=质数的个数. 思路: 设f(n)为 gcd(x,y)=p的个数,那么F(n)为 p | gcd(x,y)的个数,显然可得F(n)=(x/p)*(y/p). 这道题目因为可以是不同的质数,所以需要枚举质数, 但是这样枚举太耗时,所以在这里令t=pk, 这样一来的话,我们只需要预处理u(t/p)的前缀和,之后像之前的题一样分块处理就可以了. 1 #include<ios

* SPOJ PGCD Primes in GCD Table (需要自己推线性筛函数,好题)

题目大意: 给定n,m,求有多少组(a,b) 0<a<=n , 0<b<=m , 使得gcd(a,b)= p , p是一个素数 这里本来利用枚举一个个素数,然后利用莫比乌斯反演可以很方便得到答案,但是数据量过大,完全水不过去 题目分析过程(从别人地方抄来的) ans = sigma(p, sigma(d, μ(d) * (n/pd) * (m/pd))) Let s = pd, then ans = sigma(s, sigma(p, μ(s/p) * (n/s) * (m/s))

SPOJ4491. Primes in GCD Table(gcd(a,b)=d素数,(1&amp;lt;=a&amp;lt;=n,1&amp;lt;=b&amp;lt;=m))加强版

SPOJ4491. Primes in GCD Table Problem code: PGCD Johnny has created a table which encodes the results of some operation -- a function of two arguments. But instead of a boring multiplication table of the sort you learn by heart at prep-school, he has

SPOJ PGCD(莫比乌斯反演)

传送门:Primes in GCD Table 题意:给定两个数和,其中,,求为质数的有多少对?其中和的范围是. 分析:这题不能枚举质数来进行莫比乌斯反演,得预处理出∑υ(n/p)(n%p==0). #pragma comment(linker,"/STACK:1024000000,1024000000") #include <cstdio> #include <cstring> #include <string> #include <cmat

Codeforces 338D GCD Table 中国剩余定理

题目链接:点击打开链接 给定n*m的矩阵,[i,j]的点值为gcd(i,j) 给定一个k长的序列,问是否能匹配上 矩阵的某一行的连续k个元素 思路: 我们要求出一个解(i,j) 使得 i<=n && j<=m 此时输出 YES 对于j j % b[0] = 0 j+1 % b[1] = 0 ··· j+l % b[l] = 0 根据定理:若 a == b (mod n) => (a+c) == b+c (mod n) 所以将上式变换为 j % b[0] = 0 j % b

Codeforces Round #323 (Div. 2) C. GCD Table

C. GCD Table The GCD table G of size n × n for an array of positive integers a of length n is defined by formula Let us remind you that the greatest common divisor (GCD) of two positive integers x and y is the greatest integer that is divisor of both

SPOJ Distinct Primes 打表

题目链接:http://www.spoj.com/problems/AMR11E/ 题目大意:Lucky Number指的是有至少三个不同素数相乘得到数.问1000以内的素因子. 解题思路:可以发现1000以内的满足条件的数字非常多,因此直接筛选打表,查看每个数的不同素因子个数,如果超过三个就满足条件. 代码: 1 const int maxn = 1e4 + 5; 2 int vis[maxn]; 3 vector<int> primes, lu; 4 5 void dowork(){ 6

CODEFORCES #523 C. GCD Table

题目描述: 有一个序列,给出该序列中的数两两的gcd,并打乱顺序,求原序列. 解题思路: 首先,原序列中的数一定会在新序列中出现,而且gcd(a, b) <= a, b.那么新序列中最大和次大的数一定是原序列中的数,那第三大是不是呢?显然要先去除已经确定的数的两两gcd,再找剩下的数最大数. 代码: 写完才发现写得有点蠢. 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #incl