1. 程式人生 > >2018.10.27 bzoj3209: 花神的數論題(數位dp)

2018.10.27 bzoj3209: 花神的數論題(數位dp)

傳送門
數位 d p dp 經典題。
題面已經暗示了我們按照二進位制位來數位 d p dp
直接 d

p dp 多少個數有 1 1 1 1 , 2
2
1 1 , 3 3 1
1
…,
然後快速冪算就行了。
於是我們列舉前幾位跟 n n 相同,後面比 n n 小的方案數。
這個顯然是可以用組合數算的。
注意 n n 自己的也要算進貢獻。
程式碼:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=10000007;
ll n,C[65][65],ans=1,cnt[65];
int len,pre;
inline ll ksm(ll x,ll p){ll ret=1;for(;p;p>>=1,x=x*x%mod)if(p&1)ret=ret*x%mod;return ret;}
int main(){
	cin>>n;
	for(int i=0;i<=60;++i){
		C[i][0]=1;
		for(int j=1;j<=i;++j)C[i][j]=C[i-1][j-1]+C[i-1][j];
	}
	while((1ll<<len)<=n)++len;
	for(int i=len-1;~i;--i)if((n>>i)&1){
		for(int j=0;j+pre<=len;++j)cnt[j+pre]+=C[i][j];
		++pre;
	}
	++cnt[pre];
	for(int i=2;i<=60;++i)(ans*=ksm(i,cnt[i]))%=mod;
	cout<<ans;
	return 0;
}