[题解]luogu_P4317_花神的数论题(数位dp
虽然是二进制但是和普通的数位dp没什么差别,统计1出现次数的乘积不如统计每个出现次数的数量,然后对应快速幂一下,转化成了平时熟悉的方案数,
状态设计:dfs里传什么参就开哪些状态,可以包括是否达到上限(lmt)之类的
#pragma GCC optimize(19260817) #include<bits/stdc++.h> #define ll long long using namespace std; const int mod=10000007; ll n; ll f[51][51][51][2],num[51]; ll qpow(ll a,ll b){ ll ans=1; while(b){ if(b&1)(ans*=a)%=mod; (a*=a)%=mod; b>>=1; } return ans%mod; } ll dfs(int x,int y,int lmt,int now){//x位y个1正统计now if(x==0)return y==now; if(f[x][y][now][lmt]!=-1)return f[x][y][now][lmt]; int top=lmt?num[x]:1; ll ans=0; for(int i=0;i<=top;i++) ans+=dfs(x-1,y+(i==1),lmt&&i==top,now); f[x][y][now][lmt]=ans; return ans; } ll g[51]; ll solve(){ int len=0; while(n){ num[++len]=n&1; n>>=1; } for(int i=1;i<=50;i++){ memset(f,-1,sizeof(f)); g[i]=dfs(len,0,1,i); } ll ans=1; for(int i=1;i<=50;i++) (ans*=qpow(i,g[i]))%=mod; return ans; } int main(){ scanf("%lld",&n); printf("%lld\n",solve()); }