bzoj 3209: 花神的數論題【數位dp】
阿新 • • 發佈:2018-07-30
clas tail code 花神的數論題 turn a* names blog nsh
參考:https://blog.csdn.net/sunshinezff/article/details/51049132
非典型數位dp
首先預處理,設f[i][j]為以0開頭的i位數中1的個數為j的數的數量,g[i][j]為以1開頭的i位數中1的個數為j的數的數量;轉移是 f[i][j]=f[i-1][j]+g[i-1][j],g[i][j]=f[i-1][j-1]+g[i-1][j-1]
然後做數位dp,對於n在二進制下為1的位統計這樣的1的個數出現過幾次,然後快速冪即可
#include<iostream> #include<cstdio> using namespace std; const int N=65,mod=10000007; long long n,f[N][N],g[N][N]; long long ksm(long long a,long long b) { long long r=1ll; while(b) { if(b&1) r=r*a%mod; a=a*a%mod; b>>=1; } return r; } int main() { scanf("%lld",&n); f[1][0]=1,g[1][1]=1; for(int i=2;i<=60;i++) for(int j=0;j<=i;j++) { f[i][j]=f[i-1][j]+g[i-1][j]; if(j>0) g[i][j]=f[i-1][j-1]+g[i-1][j-1]; } long long t=0,c=0,ans=1; for(t=0;(1ll<<t)<=n;t++); for(;t;t--) if(1ll<<(t-1)&n) { for(int i=1;i<=t;i++) ans=ans*ksm(i+c,f[t][i])%mod; if(c) ans=ans*c%mod; c++; } printf("%lld\n",ans*c%mod); return 0; }
bzoj 3209: 花神的數論題【數位dp】