【bzoj 3209】花神的数论题(组合数学)
2018-01-26 11:44
489 查看
传送门biu~
令aniani代表二进制中11的个数为ii的数有多少个。从高位向低位枚举,假设输入的数nn的二进制第ii位为11,那么设一个数xx的第ii位为00,前i−1i−1位与nn相同,那么无论比ii位低的数位中哪一位为11,xx都不会大于nn,所以可以用组合数Cki−1Ci−1k更新答案。
Ps:φ(10000007)=9988440φ(10000007)=9988440
说得不清楚看代码:
令aniani代表二进制中11的个数为ii的数有多少个。从高位向低位枚举,假设输入的数nn的二进制第ii位为11,那么设一个数xx的第ii位为00,前i−1i−1位与nn相同,那么无论比ii位低的数位中哪一位为11,xx都不会大于nn,所以可以用组合数Cki−1Ci−1k更新答案。
Ps:φ(10000007)=9988440φ(10000007)=9988440
说得不清楚看代码:
#include<bits/stdc++.h> using namespace std; const long long mod=10000007,phi=9988440; long long n,ans=1; long long c[51][51],an[51]; int a[51],now,cnt; inline void getC(){ for(int i=0;i<=50;++i){ c[i][0]=1; for(int j=1;j<=i;++j) c[i][j]=c[i-1][j]+c[i-1][j-1]; } } inline long long ksm(long long p,long long n){ long long re=1; while(n){ if(n&1) re=re*p%mod; p=p*p%mod; n>>=1; } return re; } int main(){ scanf("%lld",&n); getC(); while(n){a[++cnt]=n&1;n>>=1;} for(int i=cnt;i>=1;--i){ if(!a[i]) continue; for(int j=1;j<i;++j) an[now+j]+=c[i-1][j]; ++an[++now]; } for(int i=1;i<=cnt;++i) (ans*=ksm(i,an[i]%phi))%=mod; printf("%lld",ans); return 0; }
相关文章推荐
- BZOJ3209 花神的数论题 【组合数 + 按位计数】
- Bzoj 4403: 序列统计 Lucas定理,组合数学,数论
- BZOJ 3209 花神的数论题 数位DP+数论
- BZOJ 3209 花神的数论题
- BZOJ 3209 花神的数论题
- [BZOJ3209]花神的数论题(数位dp)
- 【bzoj3209】【花神的数论题】【数位dp+快速幂】
- BZOJ 3209: 花神的数论题 数位DP
- bzoj 3209: 花神的数论题 数位dp
- 【BZOJ3209】花神的数论题 数位DP
- bzoj3209 花神的数论题 数位DP
- [BZOJ3209]花神的数论题(数位dp)
- 【BZOJ】3209: 花神的数论题
- BZOJ 3209: 花神的数论题 (数位dp)
- BZOJ 3209 花神的数论题
- BZOJ 3209 花神的数论题 数位dp
- [Bzoj3209]花神的数论题(数位dp)
- (bzoj 3209 花神的数论题)<>
- [数位dp] bzoj 3209 花神的数论题
- BZOJ 3209(花神的数论题-数位统计+1,被数据范围坑了)