• 数学课(math)


    数学课(math)

    题目描述

     

    wzy又来上数学课了…… 虽然他很菜,但是数学还是懂一丢丢的。老师出了一道题,给定一个包含nn个元素的集合P=1,2,3,…,nP=1,2,3,…,n,求有多少个集合A⊆PA⊆P,满足任意x∈Ax∈A有2x∉A2x∉A,且对于AA在PP中的补集BB,也满足任意x∈Bx∈B有2x∉B2x∉B。

    wzy花费了1E100天终于算出来了这个答案,但是可恶的caoxia居然又加了一个条件!他要求AA的大小恰好为mm,这样又有多少个AA呢?

    这回wzy真的不会了,他找到了你,希望能够得到帮助。由于答案太大,你只需要输出答案mod10000019mod10000019即可。

     

    输入

     

    第一行两个数,为n,qn,q。接下来qq行每行一个数mm,询问大小为mm的AA一共有多少个。

     

    输出

     

    共qq行,每行一个数,表示方案数mod10000019

     

    样例解释

    对于第一个样例,P={1,2,3},P可以选{1},{2},{1,3},{2,3},大小为1的两种,大小为2的也有两种

    对于第二个样例,我想到了一个绝妙的解释,可惜这里写不下。

    数据范围及约定

    subtask1:20pts,n,m,q≤20n,m,q≤20.

    subtask2:30pts,n,m,q≤5,000n,m,q≤5,000.

    subtask3:30pts,n,m≤10,000,000,q≤100,000n,m≤10,000,000,q≤100,000

    subtask4:20pts,n,m≤1018,q≤100,000n,m≤1018,q≤100,000

     

    来源

    noip2018模拟-南外


    solution

    暴力想法,把每个奇数和他乘上2的若干倍丢进数组

    可知我的集合一定要选一半

    令x=num/2;

    那么如果个数为奇数,可以选x/x+1

    为偶数则只能选x个

    假设奇数个数的数目为NA,偶数个数为NB,sum为一定得选的个数

    答案即C(NA,m-sum)*2^NB

    也就是选出m-sum个x+1 nb的可以瞎选(每个两种方案)

    注意到模数只有10000019,C(n,m)可以用lucas定理求

    lucas忘光。。。

    如果n<m可以直接return 0,因为这样子N!一定包括mod

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define ll long long
    #define mod 10000019
    using namespace std;
    int q;
    ll n,m,x,h[mod+10],ny[mod+10],num[70];
    ll work(ll a,ll num){
        ll ans=1;
        while(num){
            if(num&1)ans=ans*a;
            a=a*a;a%=mod;ans%=mod;num>>=1;
        }
        return ans;
    }
    ll C(int N,int M){
        if(N<M)return 0;
        return h[N]*ny[M]%mod*ny[N-M]%mod;
    }
    ll Lucas(ll N,ll M){
        if(!M)return 1;
        return Lucas(N/mod,M/mod)*C(N%mod,M%mod)%mod;
    }
    int main()
    {
        cin>>n>>q;
        ll x=2,la=n,cnt=0,sum=0,na=0,nb=0;
        if(la%2==0)la--;
        while(1){
             
            ll now=n/x;
            if(now%2==0)now++;
            else now+=2;
            num[++cnt]=(la-now)/2+1;
            if(cnt&1)na=na+num[cnt];
            else nb=nb+num[cnt];
            sum=sum+num[cnt]*(cnt/2);
            if(now==1)break;la=now-2;x<<=1;
        }
        h[0]=1;for(int i=1;i<mod;i++)h[i]=h[i-1]*i%mod;
        ny[mod-1]=work(h[mod-1],mod-2);
        for(int i=mod-2;i;i--)ny[i]=ny[i+1]*(i+1)%mod;ny[0]=1;
        while(q--){
            scanf("%lld",&m);
            if(m<sum||m>na+sum){puts("0");continue;}
            ll ans=Lucas(na,m-sum)*work(2,nb)%mod;
            ans=(ans+mod)%mod;
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    JavaScript设计模式与开发实践 适配器模式
    JavaScript设计模式与开发实践 状态模式
    JavaScript设计模式与开发实践 装饰者模式
    JavaScript设计模式与开发实践 中介者模式
    JavaScript设计模式与开发实践 职责链模式
    meta标签属性
    在制作网站之前,前端程序员应该考虑哪些技术细节?
    JavaScript设计模式与开发实践 享元模式
    JavaScript设计模式与开发实践 模板方法模式
    梯度下降法
  • 原文地址:https://www.cnblogs.com/liankewei/p/10358780.html
Copyright © 2020-2023  润新知