luogu3455 [POI2007]ZAP-Queries 简单的莫比乌斯反演
Posted oier
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu3455 [POI2007]ZAP-Queries 简单的莫比乌斯反演相关的知识,希望对你有一定的参考价值。
ms是莫比乌斯反演里最水的题。。。
题意:对于给定的整数a,b和d,有多少正整数对x,y,满足x<=a,y<=b,并且gcd(x,y)=d。
多组询问, T<=50000,d,a,b<=50000
稍微推下shizi
(sum_{i=1}^asum_{j=1}^b[gcd(i,j)=d])
(=sum_{i=1}^{a/k}sum_{j=1}^{b/k}[gcd(i,j)=1])
(=sum_{i=1}^{a/k}sum_{j=1}^{b/k}sum_{d|i,d|j}mu(d))
(=sum_{i=1}^{a/k}sum_{j=1}^{b/k}sum_{d|i,d|j}mu(d))
(=sum_{d=1}^nmu(d)lfloorfrac a{kd} floorlfloorfrac b{kd} floor)
连枚举倍数都不用。。。直接打个数论分块就行了。。。复杂度(O(Tsqrt n))
#include <cstdio>
#include <functional>
using namespace std;
bool visit[50010];
int prime[50010], mu[50010], tot, fuck = 50000;
int main()
{
mu[1] = 1;
for (int i = 2; i <= fuck; i++)
{
if (visit[i] == false) prime[++tot] = i, mu[i] = -1;
for (int j = 1; j <= tot && i * prime[j] <= fuck; j++)
{
visit[i * prime[j]] = true;
if (i % prime[j] == 0) break;
mu[i * prime[j]] = -mu[i];
}
mu[i] += mu[i - 1];
}
int t;
scanf("%d", &t);
while (t --> 0)
{
int n, m, k;
scanf("%d%d%d", &n, &m, &k);
n /= k, m /= k;
int res = 0;
if (n > m) swap(n, m);
for (int i = 1, j; i <= n; i = j + 1)
{
j = min(n / (n / i), m / (m / i));
res += (mu[j] - mu[i - 1]) * (n / i) * (m / i);
}
printf("%d
", res);
}
return 0;
}
40行一遍AC
于NOIWC2019 Day2晚试机
日推里出现的题,竟然挺水
NOI Linux真TM难用,累死我了
以上是关于luogu3455 [POI2007]ZAP-Queries 简单的莫比乌斯反演的主要内容,如果未能解决你的问题,请参考以下文章
luogu P3455 [POI2007]ZAP-Queries
luogu3455 [POI2007]ZAP-Queries 简单的莫比乌斯反演
BZOJ1101 & 洛谷3455:[POI2007]ZAP——题解