【洛谷P4317】花神的数论题
二进制数位 DP
题目大意:
给定 $n$ ,令 $F(x)$ 表示 $x$ 在二进制下的 $1$ 的个数,求 $\prod_{i=1}^n F(i)$。
题解:
在二进制下进行数位 dp。
令 $f[i][j][t]$ 表示当前考虑了第 $i$ 位之前,有 $j$ 位为 $1$,$t$ 表示之前的位数是否和 $n$ 的前面几位相同。
转移枚举下一位的值。
最后快速幂求乘积即可。
时间复杂度 $O(log^2 n)$。
Code:
#include<iostream>
using namespace std;
typedef long long LL;
const int md=10000007;
#define lg(x)(63-__builtin_clzll(x))
LL n,f[55][55][2];
inline int pow(int a,LL b){
int ret=1;
for(;b;b>>=1,a=(LL)a*a%md)
if(b&1)ret=(LL)ret*a%md;
return ret;
}
int main(){
cin>>n;
int w=lg(n);
f[w][0][0]=f[w][1][1]=1;
for(int i=w-1;~i;--i){
const int wg=n>>i&1;
for(int c=0;c<=w+1;++c)
for(int tg=0;tg<2;++tg){
for(int nx=0;nx<2;++nx){
f[i][c+nx][tg&&wg==nx]+=f[i+1][c][tg];
if(tg&&wg==nx)break;
}
}
}
int ans=1;
for(int i=1;i<=w+1;++i)
ans=(LL)ans*pow(i,f[0][i][0]+f[0][i][1])%md;
cout<<ans<<endl;
return 0;
}