【题解】Luogu P4317 花神的数论题 组合数
前言
今天实在是太冷了!!!
o(*////▽////*)q
导致我这个菜鸡硬生生把一道数位dp写成了组合数水过(还不是因为数位dp题解没看懂
显然题意都告诉你了,$sum(i)$表示二进制位下的几个一,可以想到组合意义,在一个$i$位的二进制数中填$j$个1的方案数
预处理个50*50的杨辉三角,完全不需要求线性逆元
最后快速幂累乘出答案即可
code
1 #include <bits/stdc++.h> 2 using namespace std; 3 namespace gengyf{ 4 #define ll long long 5 #define int long long 6 const int maxn=1e4+10; 7 const int mod=1e7+7; 8 inline int read(){ 9 int f=1,x=0;char s=getchar(); 10 while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} 11 while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} 12 return f*x; 13 } 14 int n,C[55][55],d[maxn],num[maxn],ans=1; 15 void pre(){ 16 for(int i=0;i<=50;i++)C[i][0]=1; 17 for(int i=1;i<=50;i++) 18 for(int j=1;j<=50;j++){ 19 C[i][j]=C[i-1][j]+C[i-1][j-1]; 20 } 21 } 22 int qpow(int a,int b){ 23 int tmp=1; 24 while(b){ 25 if(b&1)tmp=tmp*a%mod; 26 a=a*a%mod;b>>=1; 27 } 28 return tmp; 29 } 30 int main(){ 31 n=read(); 32 pre(); 33 int len=0,cnt=0; 34 while(n){ 35 d[++len]=n&1; 36 n>>=1; 37 } 38 for(int i=len;i;--i){ 39 if(d[i]){ 40 for(int j=1;j<i;++j) 41 num[cnt+j]+=C[i-1][j]; 42 ++num[++cnt]; 43 } 44 } 45 for(int i=1;i<=len;++i){ 46 ans=ans*qpow(i,num[i])%mod; 47 } 48 printf("%lld",ans); 49 return 0; 50 } 51 } 52 signed main(){ 53 gengyf::main(); 54 return 0; 55 }
后续
在写这篇$boke$的时候,一只大佬飘过,顺便说他用的数位dp,又被了