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); } }

猜你喜欢

转载自www.cnblogs.com/hznumqf/p/13394231.html