之江学院第0届 A qwb与支教 容斥与二分
題目鏈接:?http://115.231.222.240:8081/JudgeOnline/problem.php?cid=1005&pid=0
題目描述: 給你三個數(shù)x, y, z 和 N 輸出從1開始數(shù)第N個不是x, y, z 任意一個數(shù)的倍數(shù)的數(shù)字
解題思路: 一看到倍數(shù)我先想到素數(shù)唯一分解定理, 但是這個想法不結(jié)合實際, 因為N <= 10^17所以挨個遍歷肯定是不切合實際的, 然后我在想是不是可以可以素數(shù)篩法, 更是不行。
于是上網(wǎng)上看了題解, 既然不是倍數(shù)不好求, 那么我就先求好求的倍數(shù), ans = mid/x + mid/y + mid/z - mid/lcm(x, y) - mid/lcm(y,z) - mid/lcm(x,z) + mid/lcm(x,y,z)
其中ans 是 1 ~ ans 中是x, y, z的倍數(shù)的個數(shù)。 那么答案就應(yīng)該是true_ans + N = mid 所以再二分就可以了。 這里有一個小小的trick, 就是說lcm(x,y,z)有可能會爆longlong
特判一下即可。
代碼: ps: 網(wǎng)站交不了題, 這個代碼只是思路的實現(xiàn), 并不是AC代碼。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <string> #include <map> #include <set> #include <vector> #include <cmath> using namespace std;typedef long long LL; const LL MAXN = 1e18;LL lcm(LL a, LL b) {LL GCD = __gcd(a, b);LL ans = a / GCD;if( MAXN / ans < b ) return 0;else return ans * b; }int main() {LL x, y, z, N;while( ~scanf("%lld%lld%lld%lld", &x, &y, &z, &N) ) { // cout << x << " " << y << " " << z << " " << N << endl;LL left = 0;LL right = MAXN;while( left < right-1 ) { // cout << left << " " << right << endl;LL mid = (left + right) / 2;LL ans = mid/x + mid/y + mid/z - mid/lcm(x, y) - mid/lcm(x, z) - mid/lcm(y, z);LL t = lcm(lcm(x, y), z);if( t ) ans += mid/t;if( mid - ans >= N ) {right = mid;}else {left = mid;}}printf( "%lld\n", right );}return 0; } View Code思考: 自己還是太弱了, 我嘗試著去想, 但是還是沒想出來, 其實這道題很容易往容斥那里去想的, 畢竟都給出來了三個數(shù), 還是倍數(shù)題, 二分也不難想, 慢慢總結(jié)經(jīng)驗吧
?
轉(zhuǎn)載于:https://www.cnblogs.com/FriskyPuppy/p/7070425.html
總結(jié)
以上是生活随笔為你收集整理的之江学院第0届 A qwb与支教 容斥与二分的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何恢复osd的auth表中的权限
- 下一篇: 物联网听起来像是一个和互联网不同的网,万