BZOJ 3209 花神的数论题 - 数位DP
Solution
我的解法好像很不优美。。。
定义了$4$维数组$f[i][j][pre][k]$ 表示第$i$位, 有$j$个1, 当前位的数字为$pre$,是否比输入大$k$。。。然后进行$DP$即可
看到隔壁的$2$维很惭愧
Code
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define ll long long 5 using namespace std; 6 7 const int mod = 1e7 + 7; 8 9 int n, len, a[100]; 10 11 ll f[100][100][2][2], ans[100]; 12 ll T = 1; 13 14 ll fpow(ll a, ll b) { 15 ll re = 1; 16 for(; b; b >>= 1, a = a * a % mod) 17 if(b & 1) re = re * a % mod; 18 return re; 19 } 20 21 int main() 22 { 23 ll n; scanf("%lld", &n); 24 while(n) a[++len] = n % 2, n /= 2; 25 f[0][0][0][0] = 1; 26 for(int i = 0; i <= len; ++i) 27 for(int j = 0; j <= 55; ++j) 28 for(int k = 0; k < 2; ++k) 29 for(int pre = 0; pre < 2; ++pre) 30 if(f[i][j][pre][k]) 31 for(int x = 0; x < 2; ++x) { 32 f[i + 1][j + x][x][(k + x) > a[i + 1]] += f[i][j][pre][k]; 33 } 34 for(int i = 1; i <= 55; ++i) { 35 for(int j = 1; j < len; ++j) 36 ans[i] += f[j][i][1][0] + f[j][i][1][1]; 37 ans[i] += f[len][i][1][0]; 38 } 39 for(int i = 1; i <= 55; ++i) 40 T = T * fpow(i, ans[i]) % mod; 41 printf("%lld\n", T); 42 43 }