码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 5768(中国剩余定理+容斥)

时间:2016-07-30 16:52:19      阅读:191      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5768

题目分析:

因为满足任意一组pi和ai,即可使一个“幸运数”被“污染”,我们可以想到通过容斥来处理这个问题。当我们选定了一系列pi和ai后,题意转化为求[x,y]中被7整除余0,且被这一系列pi除余ai的数的个数,可以看成若干个同余方程联立成的一次同余方程组。然后我们就可以很自然而然的想到了中国剩余定理。需要注意的是,在处理中国剩余定理的过程中,可能会发生超出LongLong的情况,需要写个类似于快速幂的快速乘法来处理。当然计数时有很大的原理,例如小于100mod3=2的个数为100/3;满足中国剩余定理的式子就只需要除以这个数然后加一;

代码如下:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <map>
#include <queue>
#include <vector>
using namespace std;
typedef  long long LL;
const int N = 20;
const int INF = 0x3f3f3f3f;
const LL mod = 1e9+7;
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 a[20],m[20];
LL qpow(LL a,LL b,LL mod){
    a%=mod;
    LL ret=0;
    while(b){
        if(b&1)ret=(ret+a)%mod;
        b>>=1;
        a=(a+a)%mod;
    }
    return ret;
}//快速乘法
LL china(int n,LL *a,LL *m){
    LL M=1,d,y,x=0;
    for(int i=0;i<n;++i)M*=m[i];
    for(int i=0;i<n;++i){
        LL w=M/m[i];
        exgcd(m[i],w,d,d,y);
        x=(x+qpow(qpow(y,w,M),a[i],M))%M;
    }
    return (x+M)%M;
}//中国剩余定理
LL p[N],yu[N];
int main(){
    int kase=0,n,T;
    scanf("%d",&T);
    while(T--){
        LL l,r;
        scanf("%d",&n);
        cin>>l>>r;
        for(int i=0;i<n;++i)
        cin>>p[i]>>yu[i];
        int len=(1<<n);
        LL ret=r/7-(l-1)/7;
        for(int i=1;i<len;++i){
            int cnt=0;
            LL cur=1;
            for(int j=0;j<n;++j){
                if(i&(1<<j)){
                    m[cnt]=p[j];
                    a[cnt]=yu[j];
                    cnt++;
                    cur*=p[j];
                }
            }
            m[cnt]=7;
            a[cnt]=0;
            cur*=7;
            cnt++;
            LL tmp=china(cnt,a,m);
            LL sub=0;
            if(tmp>=l&&tmp<=r){
                LL cha=r-tmp;
                sub=cha/cur+1;//计数方法
            }
            else if(tmp<l){
                LL cha=r-tmp;
                sub+=cha/cur+1;
                cha=l-tmp;
                sub-=cha/cur+1;
            }
            if(cnt&1)ret+=sub;
            else ret-=sub;
        }
        printf("Case #%d: %I64d\n",++kase,ret);
    }
    return 0;
}



hdu 5768(中国剩余定理+容斥)

标签:

原文地址:http://blog.csdn.net/qq_27599517/article/details/52072989

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!