math(2018.10.27)
Posted lcxer
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了math(2018.10.27)相关的知识,希望对你有一定的参考价值。
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
");
else printf("%lld
",1ll*lucas(n-2*mn,m-mn)*c%mod);
}
}
以上是关于math(2018.10.27)的主要内容,如果未能解决你的问题,请参考以下文章