思路
跑动态规划.表示第
位的数位
,前
位已经确认的数的个数.
转移应该挺好转移的,需要用前缀和优化一下.内存可能比较大,需要滚动数组.
最后把满足要求的答案全部加起来就可以了.
复杂度为,看起来比较大,实际上基本上跑不满,还是可以过的.
代码
#include<bits/stdc++.h> using namespace std; #define MAXL 505 struct bignum{ int len, a[MAXL]; bignum(){ memset( a, 0, sizeof a ); len = 1; } friend bignum operator + ( bignum x, bignum y ){ bignum t; t.len = max( x.len, y.len ); for ( int i = 1; i <= t.len; ++i ){ t.a[i] += x.a[i] + y.a[i]; t.a[i + 1] += t.a[i] / 10; t.a[i] %= 10; } if ( t.a[t.len + 1] ) t.len++; return t; } }; int k, W; bignum f[600]; bignum ans; int main(){ scanf( "%d%d", &k, &W ); for ( int i = 1; i < 1 << k; ++i ) f[i].a[1] = 1; W = min( W, ( ( 1 << k ) - 1 ) * k ); for ( int i = 2; i <= ( W - 1 ) / k + 1; ++i ){ bignum t, tt; t = f[(1 << k) - i + 2]; for ( int j = ( 1 << k ) - i + 1; j >= 1; --j ){ tt = t + f[j]; f[j] = t; t = tt; if ( i != ( W - 1 ) / k + 1 || W % k == 0 ) ans = ans + f[j]; } } if ( W % k ) for ( int i = 1; i < 1 << ( W % k ); ++i ) ans = ans + f[i]; for ( int i = ans.len; i >= 1; --i ) printf( "%d", ans.a[i] ); return 0; }