cychester

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 }
View Code

 

posted on 2018-09-14 16:10  cychester  阅读(153)  评论(0编辑  收藏  举报

导航