• BZOJ5019 SNOI2017遗失的答案(容斥原理)


      显然存在方案的数一定是L的因数,考虑对其因子预处理答案,O(1)回答。

      考虑每个质因子,设其在g中有x个,l中有y个,则要求所有选中的数该质因子个数都在[x,y]中,且存在数的质因子个数为x、y。对于后一个限制,显然可以简单地容斥,即[x,y]-[x+1,y]-[x,y-1]+[x+1,y-1],枚举这个至多是48的,这个取最大值时因子个数是28。暴力枚举数数即可。复杂度总之O(能过)。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    #define P 1000000007
    #define ll long long
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    int n,g,l,u,m,prime[20],cnt[2][20],d[10000],ans[10000],p[10000][20],q[10000][20],a[20],tot,t,sum;
    int ksm(int a,int k)
    {
        int s=1;
        for (;k;k>>=1,a=1ll*a*a%P) if (k&1) s=1ll*s*a%P;
        return s;
    }
    void get(int k,int s)
    {
        if (k>t) {sum++;return;}
        ll x=ksm(prime[k],cnt[0][k]);
        for (int i=cnt[0][k];i<=cnt[1][k];i++)
        {
            if (s*x<=n) get(k+1,s*x);else break;
            x=1ll*x*prime[k];
        }    
    }
    void build(int k,int s)
    {
        if (k>t)
        {
            p[++tot][0]=s;
            for (int i=1;i<=t;i++) p[tot][i]=a[i];
            return;
        }
        ll x=ksm(prime[k],cnt[0][k]);
        for (int i=cnt[0][k];i<=cnt[1][k];i++)
        {
            a[k]=i;
            if (s*x<=n) build(k+1,s*x);else break;
            x=1ll*x*prime[k];
        }    
    }
    void calc(int op)
    {
        //for (int i=1;i<=t;i++) cout<<prime[i]<<' '<<cnt[0][i]<<' '<<cnt[1][i]<<endl;cout<<endl;
        sum=0;get(1,1);
        for (int i=1;i<=tot;i++)
        {
            bool flag=1;
            for (int j=1;j<=t;j++)
            if (p[i][j]<cnt[0][j]||p[i][j]>cnt[1][j]) {flag=0;break;}
            if (flag)
            {
                ans[i]+=op*ksm(2,sum-1);
                if (ans[i]<0) ans[i]+=P;if (ans[i]>=P) ans[i]-=P;
            }
        }
    }
    void dfs(int k,int op)
    {
        if (k>t) {calc(op);return;}
        dfs(k+1,op);
        cnt[0][k]++;dfs(k+1,-op);
        cnt[1][k]--;dfs(k+1,op);
        cnt[0][k]--;dfs(k+1,-op);
        cnt[1][k]++;
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj5019.in","r",stdin);
        freopen("bzoj5019.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read(),g=read(),l=read(),m=read();
        if (l%g) {for (int i=1;i<=m;i++) printf("0
    ");return 0;}
        u=l;
        for (int i=2;i*i<=u;i++)
        if (u%i==0)
        {
            prime[++t]=i,cnt[1][t]=1;u/=i;
            while (u%i==0) cnt[1][t]++,u/=i;
        }
        if (u>1) prime[++t]=u,cnt[1][t]=1;
        u=g;
        for (int i=1;i<=t;i++)
        while (u%prime[i]==0) u/=prime[i],cnt[0][i]++;
        build(1,1);
        for (int i=1;i<=tot;i++) d[i]=p[i][0];
        sort(d+1,d+tot+1);
        for (int i=1;i<=tot;i++)
            for (int j=0;j<=t;j++)
            q[i][j]=p[i][j];
        for (int i=1;i<=tot;i++)
        {
            int x=lower_bound(d+1,d+tot+1,q[i][0])-d;
            for (int j=0;j<=t;j++) p[x][j]=q[i][j];
        }
        dfs(1,1);
        while (m--)
        {
            int x=read(),y=lower_bound(d+1,d+tot+1,x)-d;
            if (d[y]!=x) {printf("0
    ");continue;}
            else printf("%d
    ",ans[y]);
        }
        return 0;
    }
  • 相关阅读:
    jQuery基础及选择器
    JavaScript面向对象
    JavaScript操作DOM
    JavaScript Bom对象
    jquery内容
    jQuery基础
    正则表达式
    表单校验
    使用jQuery操作DOM
    jQuery中的动画
  • 原文地址:https://www.cnblogs.com/Gloid/p/10205203.html
Copyright © 2020-2023  润新知