HDU - 4135 +HDU - 1796 +HDU 1695 容斥原理三题

具体可以参考http://www.cnblogs.com/kane0526/archive/2013/03/14/2795446.html
写的挺好的。。

先是比较基础的,

int prime[100];
LL gao(LL n,LL m){
    int pn=0;
    for(LL i=2;i*i<=m;++i){//求一个数的质因数的模板
        if(m%i)continue;
        while(m%i==0)m/=i;
        prime[pn++]=i;
    }
    if(m!=1)prime[pn++]=m;
    int g=(1<<pn);
    LL ret=0;
    for(LL i=1;i<g;++i){
        int tmp=i,k=0,num=1;
        for(int j=0;j<pn;++j){
            if(tmp&1)k++,num*=prime[j];
            tmp>>=1;
        }
        if(k&1)ret+=n/num;
        else ret-=n/num;
    }
    return n-ret;
}
int main(){
    int cas=0;
    int T;sf("%d",&T);
    while(T--){
        LL a,b,n;
        sf("%lld%lld%lld",&a,&b,&n);
        LL ans=gao(b,n)-gao(a-1,n);
        pf("Case #%d: %lld\n",++cas,ans);
    }
}

参考http://blog.csdn.net/acm_cxlove/article/details/7877440
然后是hdu1796的应用:其实就只是要看出
发现如果A1/B1=A2/B2那么就有一棵树看不到,所以就是找出Ai/Bi有多少种。

再可以发现A/B中,如果A,B有大于1的公约数,则A=A’*D B=B’*D,那么A/B=A’/B’,也就是存在另外一组数和这种相等,则问题转换成有多少对互质的数,枚举i,从1-M中找与i互质的数,其中1<=i<=N。
怕手生,写了个dfs版的,
居然没有快。。J

int n,m;
int prime[8];
LL ret;
int pn;
void dfs(int pos,LL now ,int step){
    if(pos>pn)return    ;
    if(step&1)ret+=m/now;
    else ret-=m/now;
    for(int i=pos+1;i<pn;++i){
        dfs(i,now*prime[i],step+1);
    }
}
LL gao(int n,int m){
    pn=0;
    for(int i=2;i*i<=m;++i){//求一个数的质因数的模板
        if(m%i)continue;
        while(m%i==0)m/=i;
        prime[pn++]=i;
    }
    if(m!=1)prime[pn++]=m;
    ret=0;
    for(int i=0;i<pn;++i){
        dfs(i,prime[i],1);
    }
    return n-ret;
}
int main(){
    int T;sf("%d",&T);
    while(T--){
        sf("%d%d",&n,&m);
        LL ans=0;
        for(int i=1;i<=n;++i){
            ans+=gao(m,i);
        }
        pf("%lld\n",ans);
    }
}

然后第三题也差不多。。。

const int maxn=100005;
bool color[maxn];
int f[maxn], phi[maxn];
int prime[maxn];
void Eular()  //欧拉函数
{
    phi[1]=1;
    int k, num=0;
    memset(color,false,sizeof(color));
    for(int i=2; i<maxn; i++)
    {
        if(!color[i])
        {
            f[num++]=i;
            phi[i]=i-1;
        }
        for(int j=0; j<num&&(k=i*f[j])<maxn; j++)
        {
            color[k]=true;
            if(i%f[j]==0)
            {
                phi[k]=phi[i]*f[j]; break;
            }
            else
                phi[k]=phi[i]*(f[j]-1);
        }
    }
}
LL  gao(int n,int m){
    int pn=0;
    for(int i=2;i*i<=m;++i){
        if(m%i)continue;
        while(m%i==0)m/=i;
        prime[pn++]=i;
    }
    if(m!=1)prime[pn++]=m;
    LL ret=0;
    int g=(1<<pn);
    for(int i=1;i<g;++i){
        int tmp=i,k=0,num=1;
        for(int j=0;j<pn;++j){
            if(tmp&1)k++,num*=prime[j];
            tmp>>=1;
        }
        if(k&1)ret+=n/num;
        else ret-=n/num;
    }
    return n-ret;
}
int main(){
    int T;sf("%d",&T);
    int cas=0;
    Eular();
    while(T--){
        ans=0;
        sf("%d%d%d%d%d",&a,&b,&c,&d,&k);
        if(k==0||k>b||k>d){pf("Case %d: 0\n",++cas);continue ;}
        b/=k;d/=k;
        if(b>d)swap(b,d);
        for(int i=1;i<=b;++i){
            ans+=phi[i];
        }
        for(int i=b+1;i<=d;++i){
            ans+=gao(b,i);
        }
        pf("Case %d: %lld\n",++cas,ans);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值