bnu——GCD SUM (莫比乌斯反演)

题目:GCD SUM

题目链接:http://www.bnuoj.com/v3/problem_show.php?pid=39872

算法:莫比乌斯反演、优化

 1 #include<stdio.h>
 2 #define N 100001
 3 typedef long long LL;
 4 bool pri[N]={0};
 5 int prim[N],po=0;
 6 int mu[N];
 7 LL f[N],ff[N];       //缩短时间
 8 /*
 9   莫比乌斯函数mu[i]的定义:
10   1. 如果 i 是素数,那么mu[i]为-1;
11   2. 如果 i 是由多个不同的素数组成的,那么mu[i]为-1或者1,取决于质因子的数量,奇数就为-1,偶数为1
12   3. 如果 i 不满上面的条件,那么mu[i]为0,比如mu[4]=0;
13   用途:想要判断1~m中有多少数与i互质,那么首先计算出i的质因子,采用容斥定理做,排除掉所有质因子的倍数,再加上被重复计算的
14   比如i=6、m=20时,首先排除2的倍数,再排除3的倍数,现在6的倍数被排除两次,就加上6的倍数数量。
15 */
16 void Init()
17 {
18   mu[1]=1;
19   for(int i=2;i<N;i++)
20   {
21     if(!pri[i])
22     {
23       prim[po++]=i;
24       mu[i]=-1;
25     }
26     for(int j=0;j<po;j++)
27     {
28       LL tmp=i*prim[j];
29       if(tmp>=N) break;
30       pri[tmp]=1;
31       mu[tmp]=mu[i]*-1;
32       if(i%prim[j]==0)
33       {
34         mu[tmp]=0;
35         break;
36       }
37     }
38   }
39   f[0]=ff[0]=0;
40   //f[]:mu的前缀和
41   for(int i=1;i<N;i++)
42   {
43     f[i]=f[i-1]+mu[i];
44     ff[i]=ff[i-1]+mu[i]*i;
45   }
46 }
47 int min(int n,int m)
48 {
49   return n>m?m:n;
50 }
51 int main()
52 {
53   Init();
54   int n,m;
55   while(scanf("%d%d",&n,&m)!=EOF)
56   {
57     LL ans=0,ansx=0,ansy=0;
58     int t=min(n,m);
59     int j=1;
60     /*
61       简化前:
62       for(int i=1;i<=t;i++)
63       {
64         ans+=mu[i]*(n/i)*(m/i);
65         可简化原因:(n/i)*(m/i)虽然i一直在变化,但很多时候是相等的,比如15/8等于1,一直到15/15还是等于1。。。
66         ansx+=mu[i]*(m/i)*(i+(n/i)*i)*(n/i)/2;
67         ...
68       }
69       n/i:得到值,随着i的增大,如果这个值一直不变,那么这些可以和在一起算。
70       n/(n/i):得到上面值得最大i,从上面的i到现在的i=n/(n/i),之间的n/i,都等于n/i
71     */
72     for(int i=1;i<=t;i=j+1)
73     {
74       j=min(n/(n/i),m/(m/i));
75       ans+=(f[j]-f[i-1])*(n/i)*(m/i);
76       ansx+=(ff[j]-ff[i-1])*(m/i)*(1+(n/i))*(n/i)/2;
77       ansy+=(ff[j]-ff[i-1])*(n/i)*(1+(m/i))*(m/i)/2;
78     }
79     printf("%lld %lld %lld\n",ans,ansx,ansy);
80   }
81   return 0;
82 }
时间: 2024-11-04 08:30:14

bnu——GCD SUM (莫比乌斯反演)的相关文章

acdream 1148 GCD SUM 莫比乌斯反演 ansx,ansy

GCD SUM Time Limit: 8000/4000MS (Java/Others)Memory Limit: 128000/64000KB (Java/Others) SubmitStatisticNext Problem Problem Description 给出N,M执行如下程序:long long  ans = 0,ansx = 0,ansy = 0;for(int i = 1; i <= N; i ++)   for(int j = 1; j <= M; j ++)     

【HDU1695】GCD(莫比乌斯反演)

[HDU1695]GCD(莫比乌斯反演) 题面 题目大意 求\(a<=x<=b,c<=y<=d\) 且\(gcd(x,y)=k\)的无序数对的个数 其中,你可以假定\(a=c=1\) 所有数都\(<=100000\) 数据组数\(<=3000\) 题解 莫比乌斯反演 作为一道莫比乌斯反演的题目 首先我们要迈出第一步 如果有\(gcd(x,y)=k\) 那么,我们就有\(gcd(\frac{x}{k},\frac{y}{k})=1\) 所以,现在问题相当于转化为了求 \(

【BZOJ2820】YY的GCD(莫比乌斯反演)

[BZOJ2820]YY的GCD(莫比乌斯反演) 题面 讨厌权限题!!!提供洛谷题面 题解 单次询问\(O(n)\)是做过的一模一样的题目 但是现在很显然不行了, 于是继续推 \[ans=\sum_{d=1}^n[d\_is\_prime]\sum_{i=1}^{n/d}[\frac{n}{id}][\frac{m}{id}]\] 老套路了 令\(T=id\) \[ans=\sum_{T=1}^{n}[\frac{n}{T}][\frac{m}{T}]\sum_{d|T}[d\_is\_prim

P2257 YY的GCD (莫比乌斯反演)

[题目链接] https://www.luogu.org/problemnew/show/P2257 // luogu-judger-enable-o2 /* ----------------------- [题解] https://www.luogu.org/blog/peng-ym/solution-p2257 [莫比乌斯反演] http://www.cnblogs.com/peng-ym/p/8647856.html [整除分块] http://www.cnblogs.com/peng-y

hdu_1695: GCD 【莫比乌斯反演】

题目链接 这题求[1,n],[1,m]gcd为k的对数.而且没有顺序. 设F(n)为公约数为n的组数个数 f(n)为最大公约数为n的组数个数 然后在纸上手动验一下F(n)和f(n)的关系,直接套公式就好了.注意要删去重复的. 关于 莫比乌斯反演 的结论 #include<bits/stdc++.h> using namespace std; typedef long long LL; const int maxn=1e6; int prime[maxn+5]; bool check[maxn+

HDU 1695 GCD (莫比乌斯反演)

传送门 GCD Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 9749    Accepted Submission(s): 3648 Problem Description Given 5 integers: a, b, c, d, k, you're to find x in a-b, y in c-d that GCD(x, y)

HDU 1695 GCD 【莫比乌斯反演例题】

GCDTime Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4291 Accepted Submission(s): 1502   Problem DescriptionGiven 5 integers: a, b, c, d, k, you're to find x in a...b, y in c...d that GCD(x, y) = k.

hdu1695 GCD(莫比乌斯反演)

题意:求(1,b)区间和(1,d)区间里面gcd(x, y) = k的数的对数(1<=x<=b , 1<= y <= d). 知识点: 莫比乌斯反演/*12*/ 线性筛求莫比乌斯反演函数: void Init() { memset(vis,0,sizeof(vis)); mu[1] = 1; cnt = 0; for(int i=2; i<N; i++) { if(!vis[i]) { prime[cnt++] = i; mu[i] = -1; } for(int j=0;

cf 990G GCD Counting (莫比乌斯反演 并查集)

990G 给你一棵树,问你有多少个点对(x,y)(x\(\leq\)y),使得(x,y)简单路径上的点权值的\(gcd\)为\(i\),对于\(i\in [1,200000]\)输出点对数目. 这题没有做出来,主要还是莫比乌斯反演时间太长不熟悉了.同时统计点对的技巧也自己没有想出来,实在是不应该. 我们设\(h(i)\)是有多少个点对(x,y)(x\(\leq\)y),使得(x,y)简单路径上的点权值的\(gcd\)为\(i\)的倍数的答案.于是有\(h(i)=\sum_{i=1}^{\lflo