zoukankan      html  css  js  c++  java
  • ACM/ICPC 之 中国剩余定理+容斥原理(HDU5768)

      二进制枚举+容斥原理+中国剩余定理

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    
    #define MAXN 20
    typedef long long LL;
    
    int n;
    int s[MAXN];
    LL a[MAXN], m[MAXN];    //a是余数,m是除数
    
    LL extented_gcd(LL a,LL b, LL &x, LL &y)   //扩展欧几里得
    {
        if(a == 0 && b == 0) return -1;
        if(b == 0){
            x = 1; y = 0; return a;
        }
        LL d = extented_gcd(b, a%b, y, x);
        y -= a/b*x;
        return d;
    }
    
    LL mult(LL a, LL k, LL m){  //快速乘法
        LL res = 0;
        while(k){
            if(k & 1LL) res = (res + a) % m;
            k >>= 1;
            a = (a << 1) % m;
        }
        return res;
    }
    
    //x = ai(mod mi)  mi之间互素
    //M = m1 * m2 * ... * mi
    //Mi'*Mi = 1 (mod mi)   Mi = M/mi
    //x = sigma(ai * Mi * M') % M
    LL CRT(LL l, LL r)  //中国剩余定理
    {
        LL M = 1, ans = 0;
        for (int i = 0; i <= n; ++i)
            if(s[i]) M *= m[i];
        for(int i = 0;i <= n;i++)
        {
            if(s[i]){
                LL Mi = M/m[i];
                LL x,y;
                extented_gcd(Mi, m[i], x,y);    //求Mi*x=1(mod m[i])
                x = (x%m[i] + m[i]) % m[i];
                ans = (ans+mult(a[i]*Mi % M, x, M)) % M;    //计算最小解
            }
        }
        return (r+M-ans)/M - (l-1+M-ans)/M; //计算[l,r]间解的个数
    }
    
    int main()
    {
        //freopen("in", "r", stdin);
        int T, cas = 0;
        scanf("%d", &T);
        while(T--){
            LL l, r;
            scanf("%d%lld%lld", &n, &l, &r);
            memset(s, 0, sizeof(s));
            m[n] = 7; a[n] = 0; s[n] = 1;
            for(int i = 0;i < n;i++)
                scanf("%lld%lld", &m[i], &a[i]);
            LL ans = 0;
            int all = 1 << n;
            for(int i = 0;i < all;i++){ //二进制枚举同余方程
                int t = i, k = 0;
                for(int j = 0;j < n;j++){
                    s[j] = t & 1;
                    t >>= 1;
                    k += s[j];  //计算同余方程个数
                }
                k = k & 1 ? -1 : 1;//容斥定理-奇减偶加
                ans += 1LL * k * CRT(l, r);
            }
            printf("Case #%d: %lld
    ", ++cas, ans);
        }
        return 0;
    }
    
  • 相关阅读:
    PHP输出语法:echo、var_dump、print、print_r区别对比
    深浅拷贝
    deepin
    linux 扩容磁盘空间
    tcpdump抓包与tcp握手
    linux 搭建FTP
    ubuntu基本配置
    linux 安装kmv创建虚拟机后网络配置
    selenium + pyautogui 实现淘宝自动登录
    pycharm 加载不出来已安装的selenium包或者其他已安装的package
  • 原文地址:https://www.cnblogs.com/Inkblots/p/5775662.html
Copyright © 2011-2022 走看看