• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
镂空的行尸
   首页       联系   管理    订阅  订阅

Lucky 7 (容斥原理 + 中国剩余定理)

题意:求满足7的倍数,不满足其他条件num % p == a 的num的个数。

思路:利用中国剩余定理我i们可以求出7的倍数,但是多算了不满足约定条件又得减去一个,但是又发现多减了,又得加回来。如此,那么应该应用容斥原理来解决问题。那么就应该是将所有的状态都遍历一下,然后根据1的个数来判断是不是+-号。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn = 30;
ll n, l, r;
ll m[maxn], a[maxn], f[maxn];

ll ex_gcd(ll a, ll b, ll &x, ll &y) {
    if(!b) {
        x = 1;
        y = 0;
        return a;
    } else {
        ll tmp = ex_gcd(b, a%b, y, x);
        y -= a / b * x;
        return tmp;
    }
}

inline ll cnt(ll k, ll m, ll x) {
    return (m - k + x) / m;
}

ll mul(ll a, ll b, ll m) {
    ll ans = 0;
    while(b) {
        if(b&1LL) {
            ans += a;
            ans %= m;
        }
        a <<= 1;
        a %= m;
        b >>= 1;
    }
    return ans;
}
ll crt(int n, ll l, ll r) {
    ll M = 1;
    for(int i = 0; i < n; i++)
        if(f[i])
            M *= m[i];

    ll ans = 0;
    for(int i = 0; i < n; i++)
        if(f[i]) {
            ll mi = M / m[i];
            ll mf, tmp;
            ex_gcd(mi, m[i], mf, tmp);
            mf = (mf % m[i] + m[i]) % m[i];

            ans += mul(mul(a[i], mi, M), mf, M);
            ans = (ans % M + M) % M;
        }
    return cnt(ans, M, r) - cnt(ans, M, l-1);
}

int main() {
    int T;
    scanf("%d", &T);
    for(int ncase = 1; ncase <= T; ncase ++) {
        scanf("%lld%lld%lld", &n, &l, &r);
        for(int i = 0; i < n; i ++) {
            scanf("%lld%lld", &m[i], &a[i]);
        }
        ll ans = 0;
        m[n] =7; a[n] = 0; f[n] = 1;
        for(int i = 0; i < (1 << n); i ++){
            int tmp = i, cn = 0;
            for(int j = 0; j < n; j ++){
                if(tmp & 1) {
                    f[j] = 1; cn ++;
                }else{
                    f[j] = 0;
                }
                tmp >>= 1;
            }
            if(cn & 1) ans -= crt(n + 1, l, r);
            else ans += crt(n + 1, l, r);
        }
        printf("Case #%d: %lld\n",ncase,ans);
    }
    return 0;
}

 

more crazy more get!
posted @ 2018-10-27 15:49  镂空的行尸  阅读(185)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3