• bzoj5019: [Snoi2017]遗失的答案


    Description

    小皮球在计算出答案之后,买了一堆皮肤,他心里很开心,但是一不小心,就忘记自己买了哪些皮肤了。==|||万
    幸的是,他还记得他把所有皮肤按照1~N来编号,他买来的那些皮肤的编号(他至少买了一款皮肤),最大公约数
    是G,最小公倍数是L。现在,有Q组询问,每组询问输入一个数字X,请你告诉小皮球,有多少种合法的购买方案中
    ,购买了皮肤X?因为答案太大了,所以你只需要输出答案mod1000000007即可。

    Input

    第一行,三个数字N,G,L,如题意所示。
    第二行,一个数字Q,表示询问个数。
    第三行,Q个数字,表示每个询问所问的X。
    N,G,L≤10^8,Q≤10^5,1≤X≤10^8

    Output

    对于每一组询问,在一行中单独输出一个整数,表示这个询问的答案。

    如果L%G非零则无解,将L的每个质因子看作一维,只有每维都取到最小(L中对应质数的次数)和最大幂次(G中对应质数的次数),才能得到对应的G和L,状压表示每一维的质因数次数是否取到最小/大值,可以选的数一定每维幂次在最小值和最大值之间,这样的数很少,在数据范围内不超过800个,分治dp得出某个数不选的方案数,用总方案数减去即得到某个数必选的方案数。时间复杂度为O((L的约数个数)*log(L的约数个数)*4^(L的不同质因子个数))

    #include<bits/stdc++.h>
    typedef int mat[259][259];
    const int P=1e9+7;
    int _(){
        int x=0,c=getchar();
        while(c<48)c=getchar();
        while(c>47)x=x*10+c-48,c=getchar();
        return x;
    }
    int n,g,l,qp,mx,fs[107],tg[107],tl[107],fp=0,ans[807];
    inline void inc(int&a,int b){a+=b-P,a+=a>>31&P;}
    struct dat{
        int v,s1,s2;
        bool operator<(const dat&w)const{return v<w.v;}
        void trans(mat a){
            for(int i=mx-1;i>=0;--i){
                int*m1=a[i],*m2=a[i|s1];
                for(int j=mx-1;j>=0;--j)inc(m2[j|s2],m1[j]);
            }
        }
    }vs[807];
    int vp=0;
    void f1(int x){
        for(int i=2;i*i<=x;++i)if(x%i==0){
            do x/=i;while(x%i==0);
            fs[fp++]=i;
        }
        if(x>1)fs[fp++]=x;
    }
    void f2(int x,int*t){
        for(int i=0;i<fp;++i)for(;x%fs[i]==0;x/=fs[i],++t[i]);
    }
    void dfs(int w,int v,int s1,int s2){
        if(w==fp){
            if(v<=n)vs[++vp]=(dat){v,s1,s2};
            return;
        }
        for(int i=0;i<=tl[w];++i,v*=fs[w]){
            if(i>=tg[w])dfs(w+1,v,s1|(i==tg[w])<<w,s2|(i==tl[w])<<w);
        }
    }
    mat F[27];
    int Fp=0,all;
    void cpy(){
        for(int i=0;i<mx;++i)memcpy(F[Fp+1][i],F[Fp][i],sizeof(int)*mx);
        ++Fp;
    }
    void solve(int L,int R){
        if(L==R){
            if(R==1){
                cpy();
                vs[1].trans(F[Fp]);
                all=F[Fp][mx-1][mx-1];
                --Fp;
            }
            ans[L]=((all-F[Fp][mx-1][mx-1])%P+P)%P;
            return;
        }
        int M=L+R>>1;
        cpy();
        for(int i=M+1;i<=R;++i)vs[i].trans(F[Fp]);
        solve(L,M);
        --Fp;
        cpy();
        for(int i=L;i<=M;++i)vs[i].trans(F[Fp]);
        solve(M+1,R);
        --Fp;
    }
    void nos(){
        while(qp--)puts("0");
        exit(0);
    }
    int main(){
        n=_(),g=_(),l=_(),qp=_();
        f1(g),f1(l);
        std::sort(fs,fs+fp);
        fp=std::unique(fs,fs+fp)-fs;
        f2(g,tg),f2(l,tl);
        if(n<g)nos();
        for(int i=0;i<fp;++i)if(tg[i]>tl[i])nos();
        dfs(0,1,0,0);
        std::sort(vs+1,vs+vp+1);
        mx=1<<fp;
        F[0][0][0]=1;
        solve(1,vp);
        while(qp--){
            int x=_(),w=std::lower_bound(vs+1,vs+vp+1,(dat){x})-vs;
            if(w<=vp&&vs[w].v==x)printf("%d
    ",ans[w]);
            else puts("0");
        }
        return 0;
    }
  • 相关阅读:
    CentOS+Nginx+PHP+MySQL详细配置(图解)
    linux下MySQL安装登录及操作
    hdu 1059 多重背包
    hdu 1754 单点更新
    poj 3264 RMQ 水题
    hdu 1114 基础完全背包
    hdu 3466 排序01背包
    poj 2923 状压dp+01背包
    hdu 2639 第k大01背包
    hdu 2184 01背包变形
  • 原文地址:https://www.cnblogs.com/ccz181078/p/7501689.html
Copyright © 2020-2023  润新知