2016多校联合第四场 HDU5768

给你 [l,r] 区间,问有多少数,是 7 的倍数,并且 mod 任何 p[i]a[i]

+ 。我先吐槽下刘汝佳 CRT 板子,简直垃圾,太相信板子,半小时的题强行卡我3小时。。

分析一下题,再看看数据范围,一眼容斥。设 Pi,Pj 是两个素数。那么 mod 他们分别等于 ai,aj 的数在 [1,lcm(Pi,Pj)] 区间只有一个,我们用 n 减去这个数在加上 lcm 就把偏移差消掉了,然后直接除以 lcm 就是这个区间中符合当前枚举的条件的数量了。然后容斥去重。注意,不能直接传入总值除以7,我们需要把 0,7 丢进CRT里跑,这样才能把某些应该消掉的数消掉,否则要出错

板子啊,一定不要太相信板子!!!。

//
//  Created by Running Photon
//  Copyright (c) 2016 Running Photon. All rights reserved.
//
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define ALL(x) x.begin(), x.end()
#define INS(x) inserter(x, x,begin())
#define ll long long
#define CLR(x) memset(x, 0, sizeof x)
using namespace std;
const int inf = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = (1 << 16) + 10;
const int maxv = 1e3 + 10;
const double eps = 1e-9;

int tot;
void exgcd(ll a, ll b, ll& d, ll& x, ll& y) {
    if(!b) {d = a; x = 1; y = 0;}
    else {exgcd(b, a%b, d, y, x); y -= x * (a / b);}
}
ll inv(ll a, ll n) { //mod n aµÄÄæ
    ll d, x, y;
    exgcd(a, n, d, x, y);
    return d == 1 ? (x + n) % n : -1;
}
/*
x = ai(mod mi)
m1 * m2 * ... * mi = M
mi之间互素
x = sigma(ai * Mi * Mi(-1)) % M
Mi = M / mi
Mi(-1) = Mi 模mi的逆
*/
ll mul(ll a, ll b, ll M) {
    ll ret = 0;
    while(b) {
        if(b & 1) ret = (ret + a) % M;
        a = a * 2 % M;
        b >>= 1;
    }
    return ret;
}
ll CRT(ll a[], ll m[], ll n) {
    ll M = 1;
    ll ans = 0;
    for(int i = 1; i <= n; i++)
        M *= m[i];
    for(int i = 1; i <= n; i++) {
        ll Mi = M / m[i];
        ll x, y, d;
        exgcd(Mi, m[i], d, x, y);
        ans = (ans + mul(x, mul(a[i], Mi, M), M)) % M;
    }
    if(ans < 0) ans += M;
    return ans;
}
ll p[22];
ll a[22];
ll A[22], m[22], all;
ll calc(ll n) {
    int state = 0;
    ll res = 0;
    for(state = 1; state < 1 << tot; state++) {
        all = 0;
        ll di = 7;
        int op = __builtin_popcount(state);
        A[++all] = 0;
        m[all] = 7;
        for(int i = 0; i < tot; i++) {
            if(state >> i & 1) {
                di *= p[i];
                A[++all] = a[i];
                m[all] = p[i];
            }
        }
        ll kk = CRT(A, m, all);
        ll tmp = (n - kk + di) / di;
        if(op & 1) res += tmp;
        else res -= tmp;
    }
    return n / 7 - res;
}


int main() {
#ifdef LOCAL
    freopen("C:\\Users\\Administrator\\Desktop\\in.txt", "r", stdin);
    freopen("C:\\Users\\Administrator\\Desktop\\out.txt","w",stdout);
#endif
//  ios_base::sync_with_stdio(0);
    int T;
    scanf("%d", &T);
    int cas = 0;
    while(T--) {
        ll n, x, y;
        scanf("%lld%lld%lld", &n, &x, &y);
        tot = n;
        for(int i = 0; i < n; i++) {
            scanf("%lld%lld", &p[i], &a[i]);
        }
        if(n == 0) printf("Case #%d: %lld\n", ++cas, y / 7 - (x - 1) / 7);
        else printf("Case #%d: %lld\n", ++cas, calc(y) - calc((x - 1)));
    }

    return 0;
}

你可能感兴趣的:(数学)