思路
跑动态规划.表示第
位的数位
,前
位已经确认的数的个数.
转移应该挺好转移的,需要用前缀和优化一下.内存可能比较大,需要滚动数组.
最后把满足要求的答案全部加起来就可以了.
复杂度为,看起来比较大,实际上基本上跑不满,还是可以过的.
代码
#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;
} 
京公网安备 11010502036488号