1. 程式人生 > 實用技巧 >HDU - 4790 Just Random 數論,容斥

HDU - 4790 Just Random 數論,容斥

隨機在[a,b] 選取一個數,隨即在[c,d]選取一個數

問 x + y 取模 p 同餘 n 的概率

其實就是計數問題。關鍵在於如何計數可以不重不漏。

麻煩點在於分類討論。對於這樣的區間問題,先簡化為0 , x 的區間。

這裡用到容斥原理,第一次做這樣的題,不是很容易想到。

分類討論相對來說感覺還算簡單?只要耐心討論,總錯不了

#pragma warning(disable:4996)

#include<iostream>
#include<algorithm>
#include<bitset>
#include<tuple>
#include
<unordered_map> #include<fstream> #include<iomanip> #include<string> #include<cmath> #include<cstring> #include<vector> #include<map> #include<set> #include<list> #include<queue> #include<stack> #include<sstream> #include<cstdio> #include
<ctime> #include<cstdlib> #define pb push_back #define INF 0x3f3f3f3f #define inf 0x7FFFFFFF #define moD 1000000003 #define pii pair<ll,ll> #define eps 1e-8 #define equals(a,b) (fabs(a-b)<eps) #define bug puts("bug") #define re register #define fi first #define se second typedef long long
ll; typedef unsigned long long ull; const ll MOD = 1e6 + 7; const int maxn = 3e5 +5; const double Inf = 10000.0; const double PI = acos(-1.0); using namespace std; ll a, b, c, d, p, m; ll f(ll a, ll b) { if (a < 0 || b < 0) return 0; ll ans = (a / p) * (b / p) * p; ll ma = a % p, mb = b % p; ans += (b / p) * (ma + 1) + (a / p) * (mb + 1); if (ma > m) { ans += min(mb, m) + 1; ll tt = (m - ma + p) % p; if (tt <= mb) ans += mb - tt + 1; } else { ll t = (m - ma + p) % p; if (t <= mb) ans += min(m - t + 1, mb - t + 1); } return ans; } ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); } int main() { int T; int kase = 1; scanf("%d", &T); while (T--) { scanf("%lld%lld%lld%lld%lld%lld", &a, &b, &c, &d, &p, &m); ll ans = f(b, d) - f(b, c - 1) - f(a - 1, d) + f(a - 1, c - 1); ll sum = (b - a + 1) * (d - c + 1); ll g = gcd(ans, sum); printf("Case #%d: %lld/%lld\n", kase++, ans / g, sum / g); } }
View Code

當然網上還有數形結合的方法,也是一種角度。

#pragma warning(disable:4996)#include<iostream>#include<algorithm>#include<bitset>#include<tuple>#include<unordered_map>#include<fstream>#include<iomanip>#include<string>#include<cmath>#include<cstring>#include<vector>#include<map>#include<set>#include<list>#include<queue>#include<stack>#include<sstream>#include<cstdio>#include<ctime>#include<cstdlib>#define pb push_back#define INF 0x3f3f3f3f#define inf 0x7FFFFFFF#define moD 1000000003#define pii pair<ll,ll>#define eps 1e-8#define equals(a,b) (fabs(a-b)<eps)#define bug puts("bug")#define re register#define fi first#define se secondtypedeflonglong ll; typedefunsignedlonglong ull; const ll MOD = 1e6 + 7; constint maxn = 3e5 +5; constdouble Inf = 10000.0; constdouble PI = acos(-1.0); usingnamespacestd; ll a, b, c, d, p, m; ll f(ll a, ll b) { if (a < 0 || b < 0) return0; ll ans = (a / p) * (b / p) * p; ll ma = a % p, mb = b % p; ans += (b / p) * (ma + 1) + (a / p) * (mb + 1); if (ma > m) { ans += min(mb, m) + 1; ll tt = (m - ma + p) % p; if (tt <= mb) ans += mb - tt + 1; } else { ll t = (m - ma + p) % p; if (t <= mb) ans += min(m - t + 1, mb - t + 1); } return ans; } ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); } int main() { int T; int kase = 1; scanf("%d", &T); while (T--) { scanf("%lld%lld%lld%lld%lld%lld", &a, &b, &c, &d, &p, &m); ll ans = f(b, d) - f(b, c - 1) - f(a - 1, d) + f(a - 1, c - 1); ll sum = (b - a + 1) * (d - c + 1); ll g = gcd(ans, sum); printf("Case #%d: %lld/%lld\n", kase++, ans / g, sum / g); } }