BZOJ 2301 [HAOI2011]Problem b (容斥+莫比烏斯反演+分塊優化 詳解)
2301: [HAOI2011]Problem b
Time Limit: 50 Sec Memory Limit: 256 MBSubmit: 2096 Solved: 909
[Submit][Status][Discuss]
Description
Input
第一行一個整數n,接下來n行每行五個整數,分別表示a、b、c、d、k
Output
共n行,每行一個整數表示滿足要求的數對(x,y)的個數
Sample Input
2 5 1 5 1
1 5 1 5 2
Sample Output
143
HINT
100%的資料滿足:1≤n≤50000,1≤a≤b≤50000,1≤c≤d≤50000,1≤k≤50000題目連結:http://www.lydsy.com/JudgeOnline/problem.php?id=2301
題目分析:首先n就是五萬,因此每次即使是O(n)的計算總的下來也是O(n^2)了,因此對於每次操作我們要讓時間複雜度小於O(n),題意很清楚
先將原式變形:
a / k <= x / k <= b / k,c / k <= y / k <= d / k,gcd(x / k, y / k) = 1,令cal(b / k,d / k)為1 <= x / k <= b / k,1 <= y / k <= d / k時取出的滿足條件的個數,則根據容斥原理有
ans = cal(b / k,d / k) - cal((a - 1) / k,d / k) - cal((c - 1) / k,b / k) + cal((a - 1) / k,(c - 1) / k),因為1~a-1和1~c-1都不在我們所求的範圍內,又減的時候這段區間減了兩次,因此要再加上一個,接下來看cal函式,這裡要用到分塊求和,如果不做優化,就是直接列舉公約數ans += mob[i] * (l / i) * (r / i)但這樣會超時,考慮到不能整除的特性,在很大一段區間內(l / i)和(r / i)的值是相同的,舉個簡單的例子,l = 10,r = 11那麼可以看出 i從6到10,l / i和r / i的值都是1,因此考慮分塊求和,從i開始最長的相等區間長度為min(l / (l / i),r / (r / i)),這裡如果不能理解的話,比如l / (l / i),設l / i = p,p表示整除時的值,那麼l / p就是從i開始整除值為p的個數了
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int const MAX = 50005;
int p[MAX], mob[MAX], sum[MAX];
bool prime[MAX];
int a, b, c, d, k;
void Mobius()
{
int pnum = 0;
memset(prime, true, sizeof(prime));
memset(sum, 0, sizeof(sum));
mob[1] = 1;
sum[1] = 1;
for(int i = 2; i < MAX; i++)
{
if(prime[i])
{
p[pnum ++] = i;
mob[i] = -1;
}
for(int j = 0; j < pnum && i * p[j] < MAX; j++)
{
prime[i * p[j]] = false;
if(i % p[j] == 0)
{
mob[i * p[j]] = 0;
break;
}
mob[i * p[j]] = -mob[i];
}
sum[i] = sum[i - 1] + mob[i];
}
}
int cal(int l, int r)
{
if(l > r)
swap(l, r);
int ans = 0;
for(int i = 1, last = 0; i <= l; i = last + 1)
{
last = min(l / (l / i), r / (r / i));
ans += (l / i) * (r / i) * (sum[last] - sum[i - 1]);
}
return ans;
}
int main()
{
Mobius();
int n;
scanf("%d", &n);
while(n --)
{
scanf("%d %d %d %d %d", &a, &b, &c, &d, &k);
int ans = 0;
ans += cal(b / k, d / k);
ans -= cal((a - 1) / k, d / k);
ans -= cal((c - 1) / k, b / k);
ans += cal((a - 1) / k, (c - 1) / k);
printf("%d\n", ans);
}
}
相關文章
- CSU 1325 A very hard problem (莫比烏斯反演+分塊求和優化)優化
- ZOJ 3868 GCD Expectation (容斥+莫比烏斯反演)GC
- HDU 1695 GCD (容斥 + 莫比烏斯反演)GC
- POJ 3904 Sky Code (容斥+莫比烏斯反演)
- HDU 5212 Code (容斥 莫比烏斯反演基礎題)
- Codeforces 548E Mike and Foam (容斥+莫比烏斯反演)
- SPOJ PGCD - Primes in GCD Table (好題! 莫比烏斯反演+分塊求和優化)GC優化
- lg容斥與反演
- BZOJ 2818 Gcd (莫比烏斯反演 或 尤拉函式)GC函式
- 莫比烏斯反演
- [BZOJ4818][Sdoi2017][容斥原理][矩陣優化DP]序列計數矩陣優化
- BZOJ 3309 DZY Loves Math (莫比烏斯反演的應用 好題)
- Hackerrank GCD Product(莫比烏斯反演)GC
- bzoj 2655: calc [容斥原理 伯努利數]
- bzoj 3812: 主旋律 [容斥原理 狀壓DP]
- 容斥原理講解
- 莫比烏斯反演學習筆記筆記
- 比較典的莫比烏斯反演
- 有標號DAG計數 [容斥原理 子集反演 組合數學 fft]FFT
- 容斥
- 狄利克雷卷積 & 莫比烏斯反演卷積
- HDU 4746 Mophues (莫比烏斯反演應用)
- 反射容斥反射
- 容斥原理
- 狄利克雷卷積與莫比烏斯反演卷積
- 演算法隨筆——數論之莫比烏斯反演演算法
- 【模板】容斥原理
- bzoj1853: [Scoi2010]幸運數字(容斥原理)
- 洛谷 P2257 YY的GCD(莫比烏斯反演)GC
- 效能優化詳解優化
- Min-Max 容斥
- SPOJ VLATTICE Visible Lattice Points (莫比烏斯反演基礎題)
- ZOJ 3435 Ideal Puzzle Bobble (莫比烏斯反演基礎題)Idea
- BZOJ 1042: [HAOI2008]硬幣購物 DP,與處理,容斥
- bzoj1042: [HAOI2008]硬幣購物(Dp+容斥原理)
- MongoDB索引優化詳解MongoDB索引優化
- Codeforces 235E Number Challenge (神定理+莫比烏斯反演)
- 遊戲裡面的容斥原理遊戲