luoguP4317 花神的数论题 数位dp
作者:互联网
这道题细节并不算太多,但是求方案数的时候一定不要乱取模!
如果非要取模的话也要遵循欧拉定理.
code:
#include <bits/stdc++.h> #define N 57 #define ll long long #define mod 10000007 #define setIO(s) freopen(s".in","r",stdin) using namespace std; ll f[N][2][N]; int num[N],cnt; int qpow(int x,ll y) { int tmp=1; for(;y;y>>=1,x=(ll)x*x%mod) if(y&1) tmp=(ll)tmp*x%mod; return tmp; } void init() { f[1][0][0]=f[1][1][1]=1; for(int i=2;i<=56;++i) { for(int j=0;j<=i;++j) { f[i][0][j]+=f[i-1][0][j]+f[i-1][1][j]; if(j) f[i][1][j]+=f[i-1][0][j-1]+f[i-1][1][j-1]; } } } ll calc(ll x,int t) { memset(num,0,sizeof(num)),cnt=0; while(x) { num[++cnt]=x&1; x>>=1; } // 先计算不满足 cnt 位的所有数字. ll ans=0; int cn=0; for(int i=1;i<cnt;++i) ans+=f[i][1][t]; for(int i=cnt;i>=1;--i) { if(num[i]&&i!=cnt&&cn<=t) ans+=f[i][0][t-cn]; cn+=num[i]; } return ans; } int main() { // setIO("input"); ll n,ans=1; init(); scanf("%lld",&n); for(int i=2;i<=56;++i) { ans=ans*1ll*qpow(i,calc(n+1,i))%mod; } printf("%lld\n",ans); return 0; }
标签:tmp,cnt,int,ll,luoguP4317,花神,mod,dp,define 来源: https://www.cnblogs.com/guangheli/p/13097699.html