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

math(2018.10.27)

时间:2018-10-28 19:28:51      阅读:117      评论:0      收藏:0      [点我收藏+]

标签:scan   amp   i+1   cst   signed   mat   for   ast   下界   

20%的数据直接暴搜就行,接下来我们考虑哪些数不能够出现在同一个集合中,就连一 条边,我们会发现前??个数被我们分成了若干条链,每条链上实际只有两种选法。
于是我们就可以考虑最暴力的\(????\)了,设\(??(??,??)\)表示当前\(????\)到第\(??\)条链,一共选了\(??\)个数的方案。如果当前链长为\(2??\),则 \(??(??,??) = 2??(?? ?1,?????)\),如果为\(2??+1\),
\(??(??,??)=??(???1,?????)+??(???1,????? ?1)\)。于是 50%的数据就可以通过了。
接下来考虑\(??\)的下界。实际上对于\(2??\)或者 \(2??+1\) 的链,它选取的下界都是\(??\)。理性感知一下,如果把所有的??减去其下界再\(dp\),实际上方程就变成了\(??(??,??) = 2??(?? ?1,??)\)或者\(??(??,??) = ??(?? ?1,??)+??(?? ?1,?? ?1)\)。于是答案就变成了某个组合数乘以 \(2\) 的幂次。我们再 考虑如何枚举链,链长最多为\(??(????????)\),因此我们可以枚举链长,由于所有链开头都是奇数, 因此对于每个链长计算一下当前长度的链有多少条就行了,这个可以解一下不等式。
对于 80% 的数据直接预处理阶乘暴力计算组合数即可,100%的数据就用lucsa算一下组合数取模即可。
代码:

#include<cstdio>
#include<cmath>
using namespace std;
int inv[11000001],fac[11000001],mod=1e7+19;
long long mn,n,q,m,c,last;
int mi(int a,int b)
{
    int ans=1;
    while(b)
    {
        if(b&1)ans=1ll*ans*a%mod;
        b>>=1;a=1ll*a*a%mod;
    }
    return ans;
}
int lucas(long long x,long long y)
{
    if (x<y)return 0;
    if (x>=mod)return 1ll*lucas(x/mod,y/mod)*lucas(x%mod,y%mod)%mod;
    else return 1ll*fac[x]*inv[y]%mod*inv[x-y]%mod;
}
signed main()
{
    scanf("%lld%lld",&n,&q);fac[0]=1;
    for(int i=1;i<mod;i++)fac[i]=1ll*fac[i-1]*i%mod;
    inv[mod-1]=mi(fac[mod-1],mod-2);
    for(int i=mod-1;i>=1;i--)inv[i-1]=1ll*inv[i]*i%mod;
    for(int i=log2(n);i>=0;i--)
    {
        int x=n>>i,y=(x+1>>1)-(last+1>>1);mn+=y*(i+1>>1);
        if(i&1)c+=y;last=x;
    }
    c=mi(2,c);
    for(int i=1;i<=q;i++)
    {
        scanf("%lld",&m);
        if(m<mn)printf("0\n");
        else printf("%lld\n",1ll*lucas(n-2*mn,m-mn)*c%mod);
    }
}

math(2018.10.27)

标签:scan   amp   i+1   cst   signed   mat   for   ast   下界   

原文地址:https://www.cnblogs.com/lcxer/p/9866200.html

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